久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

基于Docker+K8S+GitLab/SVN+Jenkins+Harbor搭建持續(xù)集成交付環(huán)境的詳細(xì)教程

瀏覽:222日期:2024-10-28 08:41:40
目錄環(huán)境搭建概述1.K8S是什么?2.為什么要用K8S?3.使用K8S有哪些好處?4.環(huán)境構(gòu)成安裝Docker環(huán)境安裝docker-compose1.下載docker-compose文件2.為docker-compose文件賦予可執(zhí)行權(quán)限3.查看docker-compose版本安裝K8S集群環(huán)境安裝K8S基礎(chǔ)環(huán)境初始化Master節(jié)點(diǎn)1.初始化Master節(jié)點(diǎn)的網(wǎng)絡(luò)環(huán)境2.初始化Master節(jié)點(diǎn)3.查看Master節(jié)點(diǎn)的初始化結(jié)果初始化Worker節(jié)點(diǎn)1.獲取join命令參數(shù)2.初始化Worker節(jié)點(diǎn)3.查看初始化結(jié)果重啟K8S集群引起的問(wèn)題1.Worker節(jié)點(diǎn)故障不能啟動(dòng)2.Pod崩潰或不能正常訪(fǎng)問(wèn)K8S安裝ingress-nginx1.創(chuàng)建ingress-nginx命名空間2.安裝ingress controller3.安裝K8S SVC:ingress-nginx4.訪(fǎng)問(wèn)K8S SVC:ingress-nginxK8S安裝gitlab代碼倉(cāng)庫(kù)1.創(chuàng)建k8s-ops命名空間2.安裝gitlab-redis3.安裝gitlab-postgresql4.安裝gitlab5.安裝完成安裝Harbor私有倉(cāng)庫(kù)1.下載Harbor的離線(xiàn)安裝版本2.解壓Harbor的安裝包3.配置Harbor4.安裝并啟動(dòng)harbor5.登錄Harbor并添加賬戶(hù)6.修改Harbor端口安裝Jenkins(一般的做法)1.安裝nfs(之前安裝過(guò)的話(huà),可以省略此步)2.創(chuàng)建nfs共享目錄3.創(chuàng)建PV4.創(chuàng)建serviceAccount5.安裝Jenkins6.創(chuàng)建Service7.安裝 ingress物理機(jī)安裝SVN1.使用yum安裝SVN2.創(chuàng)建SVN庫(kù)3.配置SVN4.啟動(dòng)SVN服務(wù)Docker安裝SVN物理機(jī)安裝Jenkins1.啟用Jenkins庫(kù)2.安裝Jenkins3.啟動(dòng)Jenkins配置Jenkins運(yùn)行環(huán)境1.登錄Jenkins2.安裝插件3.配置JenkinsJenkins發(fā)布Docker項(xiàng)目到K8s集群1.調(diào)整SpringBoot項(xiàng)目的配置2.Jenkins配置發(fā)布項(xiàng)目環(huán)境搭建概述

親愛(ài)的家人們可以到鏈接:http://xiazai.jb51.net/202105/yuanma/javayaml_jb51.rar 下載所需要的yaml文件。

1.K8S是什么?

K8S全稱(chēng)是Kubernetes,是一個(gè)全新的基于容器技術(shù)的分布式架構(gòu)領(lǐng)先方案,基于容器技術(shù),目的是實(shí)現(xiàn)資源管理的自動(dòng)化,以及跨多個(gè)數(shù)據(jù)中心的資源利用率的最大化。

如果我們的系統(tǒng)設(shè)計(jì)遵循了kubernetes的設(shè)計(jì)思想,那么傳統(tǒng)系統(tǒng)架構(gòu)中那些和業(yè)務(wù)沒(méi)有多大關(guān)系的底層代碼或功能模塊,都可以使用K8S來(lái)管理,我們不必再費(fèi)心于負(fù)載均衡的選型和部署實(shí)施問(wèn)題,不必再考慮引入或自己開(kāi)發(fā)一個(gè)復(fù)雜的服務(wù)治理框架,不必再頭疼與服務(wù)監(jiān)控和故障處理模塊的開(kāi)發(fā)。總之,使用kubernetes提供的解決方案,會(huì)大大減少開(kāi)發(fā)成本,同時(shí)可以將精力更加集中于業(yè)務(wù)本身,而且由于kubernetes提供了強(qiáng)大的自動(dòng)化機(jī)制,所以系統(tǒng)后期的運(yùn)維難度和運(yùn)維成本大幅降低。

2.為什么要用K8S?

Docker 這個(gè)新興的容器化技術(shù)當(dāng)前已經(jīng)被很多公司所采用,其從單機(jī)走向集群已成必然,而云計(jì)算的蓬勃發(fā)展正在加速這一進(jìn)程。Kubernetes 作為當(dāng)前唯一被業(yè)界廣泛認(rèn)可和看好的 Docker 分布式系統(tǒng)解決方案。可以預(yù)見(jiàn),在未來(lái)幾年內(nèi),會(huì)有大量的新系統(tǒng)選擇它,不管是運(yùn)行在企業(yè)本地服務(wù)器上還是被托管到公有云上。

3.使用K8S有哪些好處?

使用Kubernetes就是在全面部署微服務(wù)架構(gòu)。微服務(wù)架構(gòu)的核心就是將一個(gè)巨大的單體應(yīng)用分解為很多小的互相連接的微服務(wù),一個(gè)微服務(wù)背后可能有多個(gè)實(shí)例副本在支撐,副本的數(shù)量可能會(huì)隨著系統(tǒng)的負(fù)荷變化而進(jìn)行調(diào)整,內(nèi)嵌的負(fù)載均衡器在 k8s 平臺(tái)中有多個(gè)實(shí)例副本在支撐,副本的數(shù)量可能會(huì)隨著系統(tǒng)的負(fù)荷變化而進(jìn)行調(diào)整,內(nèi)嵌的負(fù)載均衡器 在k8s 平臺(tái)中發(fā)揮了重要的作用。微服務(wù)架構(gòu)使得每個(gè)服務(wù)都可以由專(zhuān)門(mén)的開(kāi)發(fā)團(tuán)隊(duì)來(lái)開(kāi)發(fā),開(kāi)發(fā)者可以自由選擇開(kāi)發(fā)技術(shù),這對(duì)于大規(guī)模團(tuán)隊(duì)來(lái)說(shuō)很有價(jià)值。另外,每個(gè)微服務(wù)獨(dú)立開(kāi)發(fā)、升級(jí)、擴(kuò)展,使得系統(tǒng)具備很高的穩(wěn)定性和快速迭代進(jìn)化能力。

4.環(huán)境構(gòu)成

整套環(huán)境的搭建包含:Docker環(huán)境的搭建、docker-compose環(huán)境的搭建、K8S集群的搭建、GitLab代碼倉(cāng)庫(kù)的搭建、SVN倉(cāng)庫(kù)的搭建、Jenkins自動(dòng)化部署環(huán)境的搭建、Harbor私有倉(cāng)庫(kù)的搭建。

本文檔中,整套環(huán)境的搭建包括:

安裝Docker環(huán)境 安裝docker-compose 安裝K8S集群環(huán)境 重啟K8S集群引起的問(wèn)題 K8S安裝ingress-nginx K8S安裝gitlab代碼倉(cāng)庫(kù) 安裝Harbor私有倉(cāng)庫(kù) 安裝Jenkins 物理機(jī)安裝SVN(推薦) 物理機(jī)安裝Jenkins(推薦) 配置Jenkins運(yùn)行環(huán)境 Jenkins發(fā)布Docker項(xiàng)目到K8S

服務(wù)器規(guī)劃

IP 主機(jī)名 節(jié)點(diǎn) 操作系統(tǒng) 192.168.0.10 test10 K8S Master CentOS 8.0.1905 192.168.0.11 test11 K8S Worker CentOS 8.0.1905 192.168.0.12 test12 K8S Worker CentOS 8.0.1905

安裝環(huán)境

軟件名稱(chēng) 軟件版本 說(shuō)明 Docker 19.03.8 提供容器環(huán)境 docker-compose 1.25.5 定義和運(yùn)行由多個(gè)容器組成的應(yīng)用 K8S 1.18.2 是一個(gè)開(kāi)源的,用于管理云平臺(tái)中多個(gè)主機(jī)上的容器化的應(yīng)用,Kubernetes的目標(biāo)是讓部署容器化的應(yīng)用簡(jiǎn)單并且高效(powerful),Kubernetes提供了應(yīng)用部署,規(guī)劃,更新,維護(hù)的一種機(jī)制。 GitLab 12.1.6 代碼倉(cāng)庫(kù) Harbor 1.10.2 私有鏡像倉(cāng)庫(kù) Jenkins 2.222.3 持續(xù)集成交付

安裝Docker環(huán)境

Docker 是一個(gè)開(kāi)源的應(yīng)用容器引擎,基于 Go 語(yǔ)言 并遵從 Apache2.0 協(xié)議開(kāi)源。

Docker 可以讓開(kāi)發(fā)者打包他們的應(yīng)用以及依賴(lài)包到一個(gè)輕量級(jí)、可移植的容器中,然后發(fā)布到任何流行的 Linux 機(jī)器上,也可以實(shí)現(xiàn)虛擬化。

本文檔基于Docker 19.03.8 版本搭建Docker環(huán)境。

在所有服務(wù)器上創(chuàng)建install_docker.sh腳本,腳本內(nèi)容如下所示。

#使用阿里云鏡像中心export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com#安裝yum工具dnf install yum*#安裝docker環(huán)境yum install -y yum-utils device-mapper-persistent-data lvm2#配置Docker的yum源yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo#安裝容器插件dnf install https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.13-3.1.el7.x86_64.rpm#指定安裝docker 19.03.8版本yum install -y docker-ce-19.03.8 docker-ce-cli-19.03.8#設(shè)置Docker開(kāi)機(jī)啟動(dòng)systemctl enable docker.service#啟動(dòng)Dockersystemctl start docker.service#查看Docker版本docker version

在每臺(tái)服務(wù)器上為install_docker.sh腳本賦予可執(zhí)行權(quán)限,并執(zhí)行腳本,如下所示。

# 賦予install_docker.sh腳本可執(zhí)行權(quán)限chmod a+x ./install_docker.sh# 執(zhí)行install_docker.sh腳本./install_docker.sh安裝docker-compose

Compose 是用于定義和運(yùn)行多容器 Docker 應(yīng)用程序的工具。通過(guò) Compose,您可以使用 YML 文件來(lái)配置應(yīng)用程序需要的所有服務(wù)。然后,使用一個(gè)命令,就可以從 YML 文件配置中創(chuàng)建并啟動(dòng)所有服務(wù)。

注意:在每臺(tái)服務(wù)器上安裝docker-compose

1.下載docker-compose文件

#下載并安裝docker-composecurl -L https://github.com/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose 2.為docker-compose文件賦予可執(zhí)行權(quán)限

#賦予docker-compose可執(zhí)行權(quán)限chmod a+x /usr/local/bin/docker-compose3.查看docker-compose版本

#查看docker-compose版本[root@binghe ~]# docker-compose versiondocker-compose version 1.25.5, build 8a1c60f6docker-py version: 4.1.0CPython version: 3.7.5OpenSSL version: OpenSSL 1.1.0l 10 Sep 2019安裝K8S集群環(huán)境

Kubernetes是一個(gè)開(kāi)源的,用于管理云平臺(tái)中多個(gè)主機(jī)上的容器化的應(yīng)用,Kubernetes的目標(biāo)是讓部署容器化的應(yīng)用簡(jiǎn)單并且高效(powerful),Kubernetes提供了應(yīng)用部署,規(guī)劃,更新,維護(hù)的一種機(jī)制。

本文檔基于K8S 1.8.12版本來(lái)搭建K8S集群

安裝K8S基礎(chǔ)環(huán)境

在所有服務(wù)器上創(chuàng)建install_k8s.sh腳本文件,腳本文件的內(nèi)容如下所示。

#################配置阿里云鏡像加速器開(kāi)始########################mkdir -p /etc/dockertee /etc/docker/daemon.json <<-’EOF’{ 'registry-mirrors': ['https://zz3sblpi.mirror.aliyuncs.com']}EOFsystemctl daemon-reloadsystemctl restart docker######################配置阿里云鏡像加速器結(jié)束##########################安裝nfs-utilsyum install -y nfs-utils#安裝wget軟件下載命令yum install -y wget#啟動(dòng)nfs-serversystemctl start nfs-server#配置nfs-server開(kāi)機(jī)自啟動(dòng)systemctl enable nfs-server#關(guān)閉防火墻systemctl stop firewalld#取消防火墻開(kāi)機(jī)自啟動(dòng)systemctl disable firewalld#關(guān)閉SeLinuxsetenforce 0sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config# 關(guān)閉 swapswapoff -ayes | cp /etc/fstab /etc/fstab_bakcat /etc/fstab_bak |grep -v swap > /etc/fstab############################修改 /etc/sysctl.conf開(kāi)始############################ 如果有配置,則修改sed -i 's#^net.ipv4.ip_forward.*#net.ipv4.ip_forward=1#g' /etc/sysctl.confsed -i 's#^net.bridge.bridge-nf-call-ip6tables.*#net.bridge.bridge-nf-call-ip6tables=1#g' /etc/sysctl.confsed -i 's#^net.bridge.bridge-nf-call-iptables.*#net.bridge.bridge-nf-call-iptables=1#g' /etc/sysctl.confsed -i 's#^net.ipv6.conf.all.disable_ipv6.*#net.ipv6.conf.all.disable_ipv6=1#g' /etc/sysctl.confsed -i 's#^net.ipv6.conf.default.disable_ipv6.*#net.ipv6.conf.default.disable_ipv6=1#g' /etc/sysctl.confsed -i 's#^net.ipv6.conf.lo.disable_ipv6.*#net.ipv6.conf.lo.disable_ipv6=1#g' /etc/sysctl.confsed -i 's#^net.ipv6.conf.all.forwarding.*#net.ipv6.conf.all.forwarding=1#g' /etc/sysctl.conf# 可能沒(méi)有,追加echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.confecho 'net.bridge.bridge-nf-call-ip6tables = 1' >> /etc/sysctl.confecho 'net.bridge.bridge-nf-call-iptables = 1' >> /etc/sysctl.confecho 'net.ipv6.conf.all.disable_ipv6 = 1' >> /etc/sysctl.confecho 'net.ipv6.conf.default.disable_ipv6 = 1' >> /etc/sysctl.confecho 'net.ipv6.conf.lo.disable_ipv6 = 1' >> /etc/sysctl.confecho 'net.ipv6.conf.all.forwarding = 1' >> /etc/sysctl.conf############################修改 /etc/sysctl.conf結(jié)束############################ 執(zhí)行命令使修改后的/etc/sysctl.conf文件生效sysctl -p################# 配置K8S的yum源開(kāi)始#############################cat <<EOF > /etc/yum.repos.d/kubernetes.repo[kubernetes]name=Kubernetesbaseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64enabled=1gpgcheck=0repo_gpgcheck=0gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpgEOF################# 配置K8S的yum源結(jié)束############################## 卸載舊版本K8Syum remove -y kubelet kubeadm kubectl# 安裝kubelet、kubeadm、kubectl,這里我安裝的是1.18.2版本,你也可以安裝1.17.2版本yum install -y kubelet-1.18.2 kubeadm-1.18.2 kubectl-1.18.2# 修改docker Cgroup Driver為systemd# # 將/usr/lib/systemd/system/docker.service文件中的這一行 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock# # 修改為 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd# 如果不修改,在添加 worker 節(jié)點(diǎn)時(shí)可能會(huì)碰到如下錯(cuò)誤# [WARNING IsDockerSystemdCheck]: detected 'cgroupfs' as the Docker cgroup driver. The recommended driver is 'systemd'. # Please follow the guide at https://kubernetes.io/docs/setup/cri/sed -i 's#^ExecStart=/usr/bin/dockerd.*#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd#g' /usr/lib/systemd/system/docker.service# 設(shè)置 docker 鏡像,提高 docker 鏡像下載速度和穩(wěn)定性# 如果訪(fǎng)問(wèn) https://hub.docker.io 速度非常穩(wěn)定,也可以跳過(guò)這個(gè)步驟,一般不需配置# curl -sSL https://kuboard.cn/install-script/set_mirror.sh | sh -s ${REGISTRY_MIRROR}# 重新加載配置文件systemctl daemon-reload#重啟 dockersystemctl restart docker# 將kubelet設(shè)置為開(kāi)機(jī)啟動(dòng)并啟動(dòng)kubeletsystemctl enable kubelet && systemctl start kubelet# 查看docker版本docker version

在每臺(tái)服務(wù)器上為install_k8s.sh腳本賦予可執(zhí)行權(quán)限,并執(zhí)行腳本

# 賦予install_k8s.sh腳本可執(zhí)行權(quán)限chmod a+x ./install_k8s.sh# 運(yùn)行install_k8s.sh腳本./install_k8s.sh初始化Master節(jié)點(diǎn)

只在test10服務(wù)器上執(zhí)行的操作。

1.初始化Master節(jié)點(diǎn)的網(wǎng)絡(luò)環(huán)境

注意:下面的命令需要在命令行手動(dòng)執(zhí)行。

# 只在 master 節(jié)點(diǎn)執(zhí)行# export 命令只在當(dāng)前 shell 會(huì)話(huà)中有效,開(kāi)啟新的 shell 窗口后,如果要繼續(xù)安裝過(guò)程,請(qǐng)重新執(zhí)行此處的 export 命令export MASTER_IP=192.168.0.10# 替換 k8s.master 為 您想要的 dnsNameexport APISERVER_NAME=k8s.master# Kubernetes 容器組所在的網(wǎng)段,該網(wǎng)段安裝完成后,由 kubernetes 創(chuàng)建,事先并不存在于物理網(wǎng)絡(luò)中export POD_SUBNET=172.18.0.1/16echo '${MASTER_IP} ${APISERVER_NAME}' >> /etc/hosts2.初始化Master節(jié)點(diǎn)

在test10服務(wù)器上創(chuàng)建init_master.sh腳本文件,文件內(nèi)容如下所示。

#!/bin/bash# 腳本出錯(cuò)時(shí)終止執(zhí)行set -eif [ ${#POD_SUBNET} -eq 0 ] || [ ${#APISERVER_NAME} -eq 0 ]; then echo -e '033[31;1m請(qǐng)確保您已經(jīng)設(shè)置了環(huán)境變量 POD_SUBNET 和 APISERVER_NAME 033[0m' echo 當(dāng)前POD_SUBNET=$POD_SUBNET echo 當(dāng)前APISERVER_NAME=$APISERVER_NAME exit 1fi# 查看完整配置選項(xiàng) https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2rm -f ./kubeadm-config.yamlcat <<EOF > ./kubeadm-config.yamlapiVersion: kubeadm.k8s.io/v1beta2kind: ClusterConfigurationkubernetesVersion: v1.18.2imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containerscontrolPlaneEndpoint: '${APISERVER_NAME}:6443'networking: serviceSubnet: '10.96.0.0/16' podSubnet: '${POD_SUBNET}' dnsDomain: 'cluster.local'EOF# kubeadm init# 初始化kebeadmkubeadm init --config=kubeadm-config.yaml --upload-certs# 配置 kubectlrm -rf /root/.kube/mkdir /root/.kube/cp -i /etc/kubernetes/admin.conf /root/.kube/config# 安裝 calico 網(wǎng)絡(luò)插件# 參考文檔 https://docs.projectcalico.org/v3.13/getting-started/kubernetes/self-managed-onprem/onpremisesecho '安裝calico-3.13.1'rm -f calico-3.13.1.yamlwget https://kuboard.cn/install-script/calico/calico-3.13.1.yamlkubectl apply -f calico-3.13.1.yaml

賦予init_master.sh腳本文件可執(zhí)行權(quán)限并執(zhí)行腳本。

# 賦予init_master.sh文件可執(zhí)行權(quán)限chmod a+x ./init_master.sh# 運(yùn)行init_master.sh腳本./init_master.sh3.查看Master節(jié)點(diǎn)的初始化結(jié)果

(1)確保所有容器組處于Running狀態(tài)

# 執(zhí)行如下命令,等待 3-10 分鐘,直到所有的容器組處于 Running 狀態(tài)watch kubectl get pod -n kube-system -o wide

具體執(zhí)行如下所示。

[root@test10 ~]# watch kubectl get pod -n kube-system -o wideEvery 2.0s: kubectl get pod -n kube-system -o wide test10: Sun May 10 11:01:32 2020NAME READY STATUS RESTARTS AGE IPNODENOMINATED NODE READINESS GATES calico-kube-controllers-5b8b769fcd-5dtlp 1/1 Running 0 118s 172.18.203.66 test10 <none> <none> calico-node-fnv8g 1/1 Running 0 118s 192.168.0.10 test10 <none> <none> coredns-546565776c-27t7h 1/1 Running 0 2m1s 172.18.203.67 test10 <none> <none> coredns-546565776c-hjb8z 1/1 Running 0 2m1s 172.18.203.65 test10 <none> <none> etcd-test10 1/1 Running 0 2m7s 192.168.0.10 test10 <none> <none> kube-apiserver-test10 1/1 Running 0 2m7s 192.168.0.10 test10 <none> <none> kube-controller-manager-test10 1/1 Running 0 2m7s 192.168.0.10 test10 <none> <none> kube-proxy-dvgsr 1/1 Running 0 2m1s 192.168.0.10 test10 <none> <none> kube-scheduler-test10 1/1 Running 0 2m7s 192.168.0.10 test10 <none>

(2) 查看 Master 節(jié)點(diǎn)初始化結(jié)果

# 查看Master節(jié)點(diǎn)的初始化結(jié)果kubectl get nodes -o wide

具體執(zhí)行如下所示。

[root@test10 ~]# kubectl get nodes -o wideNAMESTATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGEKERNEL-VERSION CONTAINER-RUNTIMEtest10 Ready master 3m28s v1.18.2 192.168.0.10 <none>CentOS Linux 8 (Core) 4.18.0-80.el8.x86_64 docker://19.3.8初始化Worker節(jié)點(diǎn)1.獲取join命令參數(shù)

在Master節(jié)點(diǎn)(test10服務(wù)器)上執(zhí)行如下命令獲取join命令參數(shù)。

kubeadm token create --print-join-command

具體執(zhí)行如下所示。

[root@test10 ~]# kubeadm token create --print-join-commandW0510 11:04:34.828126 56132 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]kubeadm join k8s.master:6443 --token 8nblts.62xytoqufwsqzko2 --discovery-token-ca-cert-hash sha256:1717cc3e34f6a56b642b5751796530e367aa73f4113d09994ac3455e33047c0d

其中,有如下一行輸出。

kubeadm join k8s.master:6443 --token 8nblts.62xytoqufwsqzko2 --discovery-token-ca-cert-hash sha256:1717cc3e34f6a56b642b5751796530e367aa73f4113d09994ac3455e33047c0d

這行代碼就是獲取到的join命令。

注意:join命令中的token的有效時(shí)間為 2 個(gè)小時(shí),2小時(shí)內(nèi),可以使用此 token 初始化任意數(shù)量的 worker 節(jié)點(diǎn)。

2.初始化Worker節(jié)點(diǎn)

針對(duì)所有的 worker 節(jié)點(diǎn)執(zhí)行,在這里,就是在test11服務(wù)器和test12服務(wù)器上執(zhí)行。

在命令分別手動(dòng)執(zhí)行如下命令。

# 只在 worker 節(jié)點(diǎn)執(zhí)行# 192.168.0.10 為 master 節(jié)點(diǎn)的內(nèi)網(wǎng) IPexport MASTER_IP=192.168.0.10# 替換 k8s.master 為初始化 master 節(jié)點(diǎn)時(shí)所使用的 APISERVER_NAMEexport APISERVER_NAME=k8s.masterecho '${MASTER_IP} ${APISERVER_NAME}' >> /etc/hosts# 替換為 master 節(jié)點(diǎn)上 kubeadm token create 命令輸出的joinkubeadm join k8s.master:6443 --token 8nblts.62xytoqufwsqzko2 --discovery-token-ca-cert-hash sha256:1717cc3e34f6a56b642b5751796530e367aa73f4113d09994ac3455e33047c0d

具體執(zhí)行如下所示。

[root@test11 ~]# export MASTER_IP=192.168.0.10[root@test11 ~]# export APISERVER_NAME=k8s.master[root@test11 ~]# echo '${MASTER_IP} ${APISERVER_NAME}' >> /etc/hosts[root@test11 ~]# kubeadm join k8s.master:6443 --token 8nblts.62xytoqufwsqzko2 --discovery-token-ca-cert-hash sha256:1717cc3e34f6a56b642b5751796530e367aa73f4113d09994ac3455e33047c0d W0510 11:08:27.709263 42795 join.go:346] [preflight] WARNING: JoinControlPane.controlPlane settings will be ignored when control-plane flag is not set.[preflight] Running pre-flight checks[WARNING FileExisting-tc]: tc not found in system path[preflight] Reading configuration from the cluster...[preflight] FYI: You can look at this config file with ’kubectl -n kube-system get cm kubeadm-config -oyaml’[kubelet-start] Downloading configuration for the kubelet from the 'kubelet-config-1.18' ConfigMap in the kube-system namespace[kubelet-start] Writing kubelet configuration to file '/var/lib/kubelet/config.yaml'[kubelet-start] Writing kubelet environment file with flags to file '/var/lib/kubelet/kubeadm-flags.env'[kubelet-start] Starting the kubelet[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...This node has joined the cluster:* Certificate signing request was sent to apiserver and a response was received.* The Kubelet was informed of the new secure connection details.Run ’kubectl get nodes’ on the control-plane to see this node join the cluster.

根據(jù)輸出結(jié)果可以看出,Worker節(jié)點(diǎn)加入了K8S集群。

注意:kubeadm join…就是master 節(jié)點(diǎn)上 kubeadm token create 命令輸出的join。

3.查看初始化結(jié)果

在Master節(jié)點(diǎn)(test10服務(wù)器)執(zhí)行如下命令查看初始化結(jié)果。

kubectl get nodes -o wide

具體執(zhí)行如下所示。

[root@test10 ~]# kubectl get nodesNAMESTATUS ROLES AGE VERSIONtest10 Ready master 20m v1.18.2test11 Ready <none> 2m46s v1.18.2test12 Ready <none> 2m46s v1.18.2

注意:kubectl get nodes命令后面加上-o wide參數(shù)可以輸出更多的信息。

重啟K8S集群引起的問(wèn)題1.Worker節(jié)點(diǎn)故障不能啟動(dòng)

Master 節(jié)點(diǎn)的 IP 地址發(fā)生變化,導(dǎo)致 worker 節(jié)點(diǎn)不能啟動(dòng)。需要重新安裝K8S集群,并確保所有節(jié)點(diǎn)都有固定的內(nèi)網(wǎng) IP 地址。

2.Pod崩潰或不能正常訪(fǎng)問(wèn)

重啟服務(wù)器后使用如下命令查看Pod的運(yùn)行狀態(tài)。

#查看所有pod的運(yùn)行情況kubectl get pods --all-namespaces

發(fā)現(xiàn)很多 Pod 不在 Running 狀態(tài),此時(shí),需要使用如下命令刪除運(yùn)行不正常的Pod。

kubectl delete pod <pod-name> -n <pod-namespece>

注意:如果Pod 是使用 Deployment、StatefulSet 等控制器創(chuàng)建的,K8S 將創(chuàng)建新的 Pod 作為替代,重新啟動(dòng)的 Pod 通常能夠正常工作。

其中,pod-name表示運(yùn)行在K8S中的pod的名稱(chēng),pod-namespece表示命名空間。例如,需要?jiǎng)h除pod名稱(chēng)為pod-test,命名空間為pod-test-namespace的pod,可以使用下面的命令。

kubectl delete pod pod-test -n pod-test-namespaceK8S安裝ingress-nginx

作為反向代理將外部流量導(dǎo)入集群內(nèi)部,將 Kubernetes 內(nèi)部的 Service 暴露給外部,在 Ingress 對(duì)象中通過(guò)域名匹配 Service,這樣就可以直接通過(guò)域名訪(fǎng)問(wèn)到集群內(nèi)部的服務(wù)了。相對(duì)于 traefik 來(lái)說(shuō),nginx-ingress 性能更加優(yōu)秀。

注意:在Master節(jié)點(diǎn)(test10服務(wù)器上執(zhí)行)

1.創(chuàng)建ingress-nginx命名空間

創(chuàng)建ingress-nginx-namespace.yaml文件,主要的作用是創(chuàng)建ingress-nginx命名空間,文件內(nèi)容如下所示。

apiVersion: v1kind: Namespacemetadata: name: ingress-nginx labels: name: ingress-nginx

執(zhí)行如下命令創(chuàng)建ingress-nginx命名空間。

kubectl apply -f ingress-nginx-namespace.yaml2.安裝ingress controller

創(chuàng)建ingress-nginx-mandatory.yaml文件,主要的作用是安裝ingress-nginx。文件內(nèi)容如下所示。

apiVersion: v1kind: Namespacemetadata: name: ingress-nginx---apiVersion: apps/v1kind: Deploymentmetadata: name: default-http-backend labels: app.kubernetes.io/name: default-http-backend app.kubernetes.io/part-of: ingress-nginx namespace: ingress-nginxspec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: default-http-backend app.kubernetes.io/part-of: ingress-nginx template: metadata: labels:app.kubernetes.io/name: default-http-backendapp.kubernetes.io/part-of: ingress-nginx spec: terminationGracePeriodSeconds: 60 containers:- name: default-http-backend # Any image is permissible as long as: # 1. It serves a 404 page at / # 2. It serves 200 on a /healthz endpoint image: registry.cn-qingdao.aliyuncs.com/kubernetes_xingej/defaultbackend-amd64:1.5 livenessProbe: httpGet: path: /healthz port: 8080 scheme: HTTP initialDelaySeconds: 30 timeoutSeconds: 5 ports: - containerPort: 8080 resources: limits: cpu: 10m memory: 20Mi requests: cpu: 10m memory: 20Mi---apiVersion: v1kind: Servicemetadata: name: default-http-backend namespace: ingress-nginx labels: app.kubernetes.io/name: default-http-backend app.kubernetes.io/part-of: ingress-nginxspec: ports: - port: 80 targetPort: 8080 selector: app.kubernetes.io/name: default-http-backend app.kubernetes.io/part-of: ingress-nginx---kind: ConfigMapapiVersion: v1metadata: name: nginx-configuration namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx---kind: ConfigMapapiVersion: v1metadata: name: tcp-services namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx---kind: ConfigMapapiVersion: v1metadata: name: udp-services namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx---apiVersion: v1kind: ServiceAccountmetadata: name: nginx-ingress-serviceaccount namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx---apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRolemetadata: name: nginx-ingress-clusterrole labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginxrules: - apiGroups: - '' resources: - configmaps - endpoints - nodes - pods - secrets verbs: - list - watch - apiGroups: - '' resources: - nodes verbs: - get - apiGroups: - '' resources: - services verbs: - get - list - watch - apiGroups: - 'extensions' resources: - ingresses verbs: - get - list - watch - apiGroups: - '' resources: - events verbs: - create - patch - apiGroups: - 'extensions' resources: - ingresses/status verbs: - update---apiVersion: rbac.authorization.k8s.io/v1beta1kind: Rolemetadata: name: nginx-ingress-role namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginxrules: - apiGroups: - '' resources: - configmaps - pods - secrets - namespaces verbs: - get - apiGroups: - '' resources: - configmaps resourceNames: # Defaults to '<election-id>-<ingress-class>' # Here: '<ingress-controller-leader>-<nginx>' # This has to be adapted if you change either parameter # when launching the nginx-ingress-controller. - 'ingress-controller-leader-nginx' verbs: - get - update - apiGroups: - '' resources: - configmaps verbs: - create - apiGroups: - '' resources: - endpoints verbs: - get---apiVersion: rbac.authorization.k8s.io/v1beta1kind: RoleBindingmetadata: name: nginx-ingress-role-nisa-binding namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginxroleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: nginx-ingress-rolesubjects: - kind: ServiceAccount name: nginx-ingress-serviceaccount namespace: ingress-nginx---apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRoleBindingmetadata: name: nginx-ingress-clusterrole-nisa-binding labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginxroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: nginx-ingress-clusterrolesubjects: - kind: ServiceAccount name: nginx-ingress-serviceaccount namespace: ingress-nginx---apiVersion: apps/v1kind: Deploymentmetadata: name: nginx-ingress-controller namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginxspec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx template: metadata: labels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx annotations:prometheus.io/port: '10254'prometheus.io/scrape: 'true' spec: serviceAccountName: nginx-ingress-serviceaccount containers:- name: nginx-ingress-controller image: registry.cn-qingdao.aliyuncs.com/kubernetes_xingej/nginx-ingress-controller:0.20.0 args: - /nginx-ingress-controller - --default-backend-service=$(POD_NAMESPACE)/default-http-backend - --configmap=$(POD_NAMESPACE)/nginx-configuration - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services - --udp-services-configmap=$(POD_NAMESPACE)/udp-services - --publish-service=$(POD_NAMESPACE)/ingress-nginx - --annotations-prefix=nginx.ingress.kubernetes.io securityContext: capabilities: drop:- ALL add:- NET_BIND_SERVICE # www-data -> 33 runAsUser: 33 env: - name: POD_NAME valueFrom:fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom:fieldRef: fieldPath: metadata.namespace ports: - name: http containerPort: 80 - name: https containerPort: 443 livenessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1---

執(zhí)行如下命令安裝ingress controller。

kubectl apply -f ingress-nginx-mandatory.yaml3.安裝K8S SVC:ingress-nginx

主要是用來(lái)用于暴露pod:nginx-ingress-controller。

創(chuàng)建service-nodeport.yaml文件,文件內(nèi)容如下所示。

apiVersion: v1kind: Servicemetadata: name: ingress-nginx namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginxspec: type: NodePort ports: - name: http port: 80 targetPort: 80 protocol: TCP nodePort: 30080 - name: https port: 443 targetPort: 443 protocol: TCP nodePort: 30443 selector: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx

執(zhí)行如下命令安裝。

kubectl apply -f service-nodeport.yaml4.訪(fǎng)問(wèn)K8S SVC:ingress-nginx

查看ingress-nginx命名空間的部署情況,如下所示。

[root@test10 k8s]# kubectl get pod -n ingress-nginxNAMEREADY STATUS RESTARTS AGEdefault-http-backend-796ddcd9b-vfmgn1/1 Running 1 10hnginx-ingress-controller-58985cc996-87754 1/1 Running 2 10h

在命令行服務(wù)器命令行輸入如下命令查看ingress-nginx的端口映射情況。

kubectl get svc -n ingress-nginx

具體如下所示。

[root@test10 k8s]# kubectl get svc -n ingress-nginx NAME TYPECLUSTER-IP EXTERNAL-IP PORT(S) AGEdefault-http-backend ClusterIP 10.96.247.2 <none>80/TCP 7m3singress-nginx NodePort 10.96.40.6 <none>80:30080/TCP,443:30443/TCP 4m35s

所以,可以通過(guò)Master節(jié)點(diǎn)(test10服務(wù)器)的IP地址和30080端口號(hào)來(lái)訪(fǎng)問(wèn)ingress-nginx,如下所示。

[root@test10 k8s]# curl 192.168.0.10:30080 default backend - 404

也可以在瀏覽器打開(kāi)http://192.168.0.10:30080 來(lái)訪(fǎng)問(wèn)ingress-nginx,如下所示。

K8S安裝gitlab代碼倉(cāng)庫(kù)

GitLab是由GitLabInc.開(kāi)發(fā),使用MIT許可證的基于網(wǎng)絡(luò)的Git倉(cāng)庫(kù)管理工具,且具有Wiki和issue跟蹤功能。使用Git作為代碼管理工具,并在此基礎(chǔ)上搭建起來(lái)的web服務(wù)。

注意:在Master節(jié)點(diǎn)(test10服務(wù)器上執(zhí)行)

1.創(chuàng)建k8s-ops命名空間

創(chuàng)建k8s-ops-namespace.yaml文件,主要作用是創(chuàng)建k8s-ops命名空間。文件內(nèi)容如下所示。

apiVersion: v1kind: Namespacemetadata: name: k8s-ops labels: name: k8s-ops

執(zhí)行如下命令創(chuàng)建命名空間。

kubectl apply -f k8s-ops-namespace.yaml 2.安裝gitlab-redis

創(chuàng)建gitlab-redis.yaml文件,文件的內(nèi)容如下所示。

apiVersion: apps/v1kind: Deploymentmetadata: name: redis namespace: k8s-ops labels: name: redisspec: selector: matchLabels: name: redis template: metadata: name: redis labels:name: redis spec: containers: - name: redisimage: sameersbn/redisimagePullPolicy: IfNotPresentports:- name: redis containerPort: 6379volumeMounts:- mountPath: /var/lib/redis name: datalivenessProbe: exec: command: - redis-cli - ping initialDelaySeconds: 30 timeoutSeconds: 5readinessProbe: exec: command: - redis-cli - ping initialDelaySeconds: 10 timeoutSeconds: 5 volumes: - name: datahostPath: path: /data1/docker/xinsrv/redis---apiVersion: v1kind: Servicemetadata: name: redis namespace: k8s-ops labels: name: redisspec: ports: - name: redis port: 6379 targetPort: redis selector: name: redis

首先,在命令行執(zhí)行如下命令創(chuàng)建/data1/docker/xinsrv/redis目錄。

mkdir -p /data1/docker/xinsrv/redis

執(zhí)行如下命令安裝gitlab-redis。

kubectl apply -f gitlab-redis.yaml 3.安裝gitlab-postgresql

創(chuàng)建gitlab-postgresql.yaml,文件內(nèi)容如下所示。

apiVersion: apps/v1kind: Deploymentmetadata: name: postgresql namespace: k8s-ops labels: name: postgresqlspec: selector: matchLabels: name: postgresql template: metadata: name: postgresql labels:name: postgresql spec: containers: - name: postgresqlimage: sameersbn/postgresqlimagePullPolicy: IfNotPresentenv:- name: DB_USER value: gitlab- name: DB_PASS value: passw0rd- name: DB_NAME value: gitlab_production- name: DB_EXTENSION value: pg_trgmports:- name: postgres containerPort: 5432volumeMounts:- mountPath: /var/lib/postgresql name: datalivenessProbe: exec: command: - pg_isready - -h - localhost - -U - postgres initialDelaySeconds: 30 timeoutSeconds: 5readinessProbe: exec: command: - pg_isready - -h - localhost - -U - postgres initialDelaySeconds: 5 timeoutSeconds: 1 volumes: - name: datahostPath: path: /data1/docker/xinsrv/postgresql---apiVersion: v1kind: Servicemetadata: name: postgresql namespace: k8s-ops labels: name: postgresqlspec: ports: - name: postgres port: 5432 targetPort: postgres selector: name: postgresql

首先,執(zhí)行如下命令創(chuàng)建/data1/docker/xinsrv/postgresql目錄。

mkdir -p /data1/docker/xinsrv/postgresql

接下來(lái),安裝gitlab-postgresql,如下所示。

kubectl apply -f gitlab-postgresql.yaml4.安裝gitlab

(1)配置用戶(hù)名和密碼

首先,在命令行使用base64編碼為用戶(hù)名和密碼進(jìn)行轉(zhuǎn)碼,本示例中,使用的用戶(hù)名為admin,密碼為admin.1231

轉(zhuǎn)碼情況如下所示。

[root@test10 k8s]# echo -n ’admin’ | base64 YWRtaW4=[root@test10 k8s]# echo -n ’admin.1231’ | base64 YWRtaW4uMTIzMQ==

轉(zhuǎn)碼后的用戶(hù)名為:YWRtaW4= 密碼為:YWRtaW4uMTIzMQ==

也可以對(duì)base64編碼后的字符串解碼,例如,對(duì)密碼字符串解碼,如下所示。

[root@test10 k8s]# echo ’YWRtaW4uMTIzMQ==’ | base64 --decode admin.1231

接下來(lái),創(chuàng)建secret-gitlab.yaml文件,主要是用戶(hù)來(lái)配置GitLab的用戶(hù)名和密碼,文件內(nèi)容如下所示。

apiVersion: v1kind: Secretmetadata: namespace: k8s-ops name: git-user-passtype: Opaquedata: username: YWRtaW4= password: YWRtaW4uMTIzMQ==

執(zhí)行配置文件的內(nèi)容,如下所示。

kubectl create -f ./secret-gitlab.yaml

(2)安裝GitLab

創(chuàng)建gitlab.yaml文件,文件的內(nèi)容如下所示。

apiVersion: apps/v1kind: Deploymentmetadata: name: gitlab namespace: k8s-ops labels: name: gitlabspec: selector: matchLabels: name: gitlab template: metadata: name: gitlab labels:name: gitlab spec: containers: - name: gitlabimage: sameersbn/gitlab:12.1.6imagePullPolicy: IfNotPresentenv:- name: TZ value: Asia/Shanghai- name: GITLAB_TIMEZONE value: Beijing- name: GITLAB_SECRETS_DB_KEY_BASE value: long-and-random-alpha-numeric-string- name: GITLAB_SECRETS_SECRET_KEY_BASE value: long-and-random-alpha-numeric-string- name: GITLAB_SECRETS_OTP_KEY_BASE value: long-and-random-alpha-numeric-string- name: GITLAB_ROOT_PASSWORD valueFrom: secretKeyRef: name: git-user-pass key: password- name: GITLAB_ROOT_EMAIL value: 12345678@qq.com- name: GITLAB_HOST value: gitlab.binghe.com- name: GITLAB_PORT value: '80'- name: GITLAB_SSH_PORT value: '30022'- name: GITLAB_NOTIFY_ON_BROKEN_BUILDS value: 'true'- name: GITLAB_NOTIFY_PUSHER value: 'false'- name: GITLAB_BACKUP_SCHEDULE value: daily- name: GITLAB_BACKUP_TIME value: 01:00- name: DB_TYPE value: postgres- name: DB_HOST value: postgresql- name: DB_PORT value: '5432'- name: DB_USER value: gitlab- name: DB_PASS value: passw0rd- name: DB_NAME value: gitlab_production- name: REDIS_HOST value: redis- name: REDIS_PORT value: '6379'ports:- name: http containerPort: 80- name: ssh containerPort: 22volumeMounts:- mountPath: /home/git/data name: datalivenessProbe: httpGet: path: / port: 80 initialDelaySeconds: 180 timeoutSeconds: 5readinessProbe: httpGet: path: / port: 80 initialDelaySeconds: 5 timeoutSeconds: 1 volumes: - name: datahostPath: path: /data1/docker/xinsrv/gitlab---apiVersion: v1kind: Servicemetadata: name: gitlab namespace: k8s-ops labels: name: gitlabspec: ports: - name: http port: 80 nodePort: 30088 - name: ssh port: 22 targetPort: ssh nodePort: 30022 type: NodePort selector: name: gitlab---apiVersion: extensions/v1beta1kind: Ingressmetadata: name: gitlab namespace: k8s-ops annotations: kubernetes.io/ingress.class: traefikspec: rules: - host: gitlab.binghe.com http: paths: - backend: serviceName: gitlab servicePort: http

注意:在配置GitLab時(shí),監(jiān)聽(tīng)主機(jī)時(shí),不能使用IP地址,需要使用主機(jī)名或者域名,上述配置中,我使用的是gitlab.binghe.com主機(jī)名。

在命令行執(zhí)行如下命令創(chuàng)建/data1/docker/xinsrv/gitlab目錄。

mkdir -p /data1/docker/xinsrv/gitlab

安裝GitLab,如下所示。

kubectl apply -f gitlab.yaml5.安裝完成

查看k8s-ops命名空間部署情況,如下所示。

[root@test10 k8s]# kubectl get pod -n k8s-opsNAME READY STATUS RESTARTS AGEgitlab-7b459db47c-5vk6t 0/1 Running 0 11spostgresql-79567459d7-x52vx 1/1 Running 0 30mredis-67f4cdc96c-h5ckz1/1 Running 1 10h

也可以使用如下命令查看。

[root@test10 k8s]# kubectl get pod --namespace=k8s-opsNAME READY STATUS RESTARTS AGEgitlab-7b459db47c-5vk6t 0/1 Running 0 36spostgresql-79567459d7-x52vx 1/1 Running 0 30mredis-67f4cdc96c-h5ckz1/1 Running 1 10h

二者效果一樣。

接下來(lái),查看GitLab的端口映射,如下所示。

[root@test10 k8s]# kubectl get svc -n k8s-opsNAME TYPECLUSTER-IP EXTERNAL-IP PORT(S) AGEgitlab NodePort 10.96.153.100 <none>80:30088/TCP,22:30022/TCP 2m42spostgresql ClusterIP 10.96.203.119 <none>5432/TCP 32mredisClusterIP 10.96.107.150 <none>6379/TCP 10h

此時(shí),可以看到,可以通過(guò)Master節(jié)點(diǎn)(test10)的主機(jī)名gitlab.binghe.com和端口30088就能夠訪(fǎng)問(wèn)GitLab。由于我這里使用的是虛擬機(jī)來(lái)搭建相關(guān)的環(huán)境,在本機(jī)訪(fǎng)問(wèn)虛擬機(jī)映射的gitlab.binghe.com時(shí),需要配置本機(jī)的hosts文件,在本機(jī)的hosts文件中加入如下配置項(xiàng)。

192.168.0.10 gitlab.binghe.com

注意:在Windows操作系統(tǒng)中,hosts文件所在的目錄如下。

C:WindowsSystem32driversetc

接下來(lái),就可以在瀏覽器中通過(guò)鏈接:http://gitlab.binghe.com:30088 來(lái)訪(fǎng)問(wèn)GitLab了,如下所示。

此時(shí),可以通過(guò)用戶(hù)名root和密碼admin.1231來(lái)登錄GitLab了。

注意:這里的用戶(hù)名是root而不是admin,因?yàn)閞oot是GitLab默認(rèn)的超級(jí)用戶(hù)。

到此,K8S安裝gitlab完成。

安裝Harbor私有倉(cāng)庫(kù)

Habor是由VMWare公司開(kāi)源的容器鏡像倉(cāng)庫(kù)。事實(shí)上,Habor是在Docker Registry上進(jìn)行了相應(yīng)的企業(yè)級(jí)擴(kuò)展,從而獲得了更加廣泛的應(yīng)用,這些新的企業(yè)級(jí)特性包括:管理用戶(hù)界面,基于角色的訪(fǎng)問(wèn)控制 ,AD/LDAP集成以及審計(jì)日志等,足以滿(mǎn)足基本企業(yè)需求。

注意:這里將Harbor私有倉(cāng)庫(kù)安裝在Master節(jié)點(diǎn)(test10服務(wù)器)上,實(shí)際生產(chǎn)環(huán)境中建議安裝在其他服務(wù)器。

1.下載Harbor的離線(xiàn)安裝版本

wget https://github.com/goharbor/harbor/releases/download/v1.10.2/harbor-offline-installer-v1.10.2.tgz2.解壓Harbor的安裝包

tar -zxvf harbor-offline-installer-v1.10.2.tgz

解壓成功后,會(huì)在服務(wù)器當(dāng)前目錄生成一個(gè)harbor目錄。

3.配置Harbor

注意:這里,我將Harbor的端口修改成了1180,如果不修改Harbor的端口,默認(rèn)的端口是80。

(1)修改harbor.yml文件

cd harborvim harbor.yml

修改的配置項(xiàng)如下所示。

hostname: 192.168.0.10http: port: 1180harbor_admin_password: binghe123###并把https注釋掉,不然在安裝的時(shí)候會(huì)報(bào)錯(cuò):ERROR:root:Error: The protocol is https but attribute ssl_cert is not set#https: #port: 443 #certificate: /your/certificate/path #private_key: /your/private/key/path

(2)修改daemon.json文件

修改/etc/docker/daemon.json文件,沒(méi)有的話(huà)就創(chuàng)建,在/etc/docker/daemon.json文件中添加如下內(nèi)容。

[root@binghe~]# cat /etc/docker/daemon.json{ 'registry-mirrors': ['https://zz3sblpi.mirror.aliyuncs.com'], 'insecure-registries':['192.168.0.10:1180']}

也可以在服務(wù)器上使用 ip addr 命令查看本機(jī)所有的IP地址段,將其配置到/etc/docker/daemon.json文件中。這里,我配置后的文件內(nèi)容如下所示。

{ 'registry-mirrors': ['https://zz3sblpi.mirror.aliyuncs.com'], 'insecure-registries':['192.168.175.0/16','172.17.0.0/16', '172.18.0.0/16', '172.16.29.0/16', '192.168.0.10:1180']}4.安裝并啟動(dòng)harbor

配置完成后,輸入如下命令即可安裝并啟動(dòng)Harbor

[root@binghe harbor]# ./install.sh 5.登錄Harbor并添加賬戶(hù)

安裝成功后,在瀏覽器地址欄輸入http://192.168.0.10:1180打開(kāi)鏈接,輸入用戶(hù)名admin和密碼binghe123,登錄系統(tǒng)。

接下來(lái),我們選擇用戶(hù)管理,添加一個(gè)管理員賬戶(hù),為后續(xù)打包Docker鏡像和上傳Docker鏡像做準(zhǔn)備。

密碼為Binghe123。點(diǎn)擊確,此時(shí),賬戶(hù)binghe還不是管理員,此時(shí)選中binghe賬戶(hù),點(diǎn)擊“設(shè)置為管理員”。

此時(shí),binghe賬戶(hù)就被設(shè)置為管理員了。到此,Harbor的安裝就完成了。

6.修改Harbor端口

如果安裝Harbor后,大家需要修改Harbor的端口,可以按照如下步驟修改Harbor的端口,這里,我以將80端口修改為1180端口為例

(1)修改harbor.yml文件

cd harborvim harbor.yml

修改的配置項(xiàng)如下所示。

hostname: 192.168.0.10http: port: 1180harbor_admin_password: binghe123###并把https注釋掉,不然在安裝的時(shí)候會(huì)報(bào)錯(cuò):ERROR:root:Error: The protocol is https but attribute ssl_cert is not set#https: #port: 443 #certificate: /your/certificate/path #private_key: /your/private/key/path

(2)修改docker-compose.yml文件

vim docker-compose.yml

修改的配置項(xiàng)如下所示。

ports: - 1180:80

(3)修改config.yml文件

cd common/config/registryvim config.yml

修改的配置項(xiàng)如下所示。

realm: http://192.168.0.10:1180/service/token

(4)重啟Docker

systemctl daemon-reloadsystemctl restart docker.service

(5)重啟Harbor

[root@binghe harbor]# docker-compose downStopping harbor-log ... doneRemoving nginx ... doneRemoving harbor-portal ... doneRemoving harbor-jobservice ... doneRemoving harbor-core ... doneRemoving redis ... doneRemoving registry ... doneRemoving registryctl ... doneRemoving harbor-db ... doneRemoving harbor-log... doneRemoving network harbor_harbor [root@binghe harbor]# ./prepareprepare base dir is set to /mnt/harborClearing the configuration file: /config/log/logrotate.confClearing the configuration file: /config/nginx/nginx.confClearing the configuration file: /config/core/envClearing the configuration file: /config/core/app.confClearing the configuration file: /config/registry/root.crtClearing the configuration file: /config/registry/config.ymlClearing the configuration file: /config/registryctl/envClearing the configuration file: /config/registryctl/config.ymlClearing the configuration file: /config/db/envClearing the configuration file: /config/jobservice/envClearing the configuration file: /config/jobservice/config.ymlGenerated configuration file: /config/log/logrotate.confGenerated configuration file: /config/nginx/nginx.confGenerated configuration file: /config/core/envGenerated configuration file: /config/core/app.confGenerated configuration file: /config/registry/config.ymlGenerated configuration file: /config/registryctl/envGenerated configuration file: /config/db/envGenerated configuration file: /config/jobservice/envGenerated configuration file: /config/jobservice/config.ymlloaded secret from file: /secret/keys/secretkeyGenerated configuration file: /compose_location/docker-compose.ymlClean up the input dir [root@binghe harbor]# docker-compose up -dCreating network 'harbor_harbor' with the default driverCreating harbor-log ... doneCreating harbor-db ... doneCreating redis ... doneCreating registry ... doneCreating registryctl ... doneCreating harbor-core ... doneCreating harbor-jobservice ... doneCreating harbor-portal ... doneCreating nginx ... done [root@binghe harbor]# docker ps -aCONTAINER IDIMAGE COMMAND CREATED STATUS PORTS安裝Jenkins(一般的做法)

Jenkins是一個(gè)開(kāi)源的、提供友好操作界面的持續(xù)集成(CI)工具,起源于Hudson(Hudson是商用的),主要用于持續(xù)、自動(dòng)的構(gòu)建/測(cè)試軟件項(xiàng)目、監(jiān)控外部任務(wù)的運(yùn)行(這個(gè)比較抽象,暫且寫(xiě)上,不做解釋?zhuān)enkins用Java語(yǔ)言編寫(xiě),可在Tomcat等流行的servlet容器中運(yùn)行,也可獨(dú)立運(yùn)行。通常與版本管理工具(SCM)、構(gòu)建工具結(jié)合使用。常用的版本控制工具有SVN、GIT,構(gòu)建工具有Maven、Ant、Gradle。

1.安裝nfs(之前安裝過(guò)的話(huà),可以省略此步)

使用 nfs 最大的問(wèn)題就是寫(xiě)權(quán)限,可以使用 kubernetes 的 securityContext/runAsUser 指定 jenkins 容器中運(yùn)行 jenkins 的用戶(hù) uid,以此來(lái)指定 nfs 目錄的權(quán)限,讓 jenkins 容器可寫(xiě);也可以不限制,讓所有用戶(hù)都可以寫(xiě)。這里為了簡(jiǎn)單,就讓所有用戶(hù)可寫(xiě)了。

如果之前已經(jīng)安裝過(guò)nfs,則這一步可以省略。找一臺(tái)主機(jī),安裝 nfs,這里,我以在Master節(jié)點(diǎn)(test10服務(wù)器)上安裝nfs為例。

在命令行輸入如下命令安裝并啟動(dòng)nfs。

yum install nfs-utils -ysystemctl start nfs-serversystemctl enable nfs-server2.創(chuàng)建nfs共享目錄

在Master節(jié)點(diǎn)(test10服務(wù)器)上創(chuàng)建 /opt/nfs/jenkins-data目錄作為nfs的共享目錄,如下所示。

mkdir -p /opt/nfs/jenkins-data

接下來(lái),編輯/etc/exports文件,如下所示。

vim /etc/exports

在/etc/exports文件文件中添加如下一行配置。

/opt/nfs/jenkins-data 192.168.175.0/24(rw,all_squash)

這里的 ip 使用 kubernetes node 節(jié)點(diǎn)的 ip 范圍,后面的 all_squash 選項(xiàng)會(huì)將所有訪(fǎng)問(wèn)的用戶(hù)都映射成 nfsnobody 用戶(hù),不管你是什么用戶(hù)訪(fǎng)問(wèn),最終都會(huì)壓縮成 nfsnobody,所以只要將 /opt/nfs/jenkins-data 的屬主改為 nfsnobody,那么無(wú)論什么用戶(hù)來(lái)訪(fǎng)問(wèn)都具有寫(xiě)權(quán)限。

這個(gè)選項(xiàng)在很多機(jī)器上由于用戶(hù) uid 不規(guī)范導(dǎo)致啟動(dòng)進(jìn)程的用戶(hù)不同,但是同時(shí)要對(duì)一個(gè)共享目錄具有寫(xiě)權(quán)限時(shí)很有效。

接下來(lái),為 /opt/nfs/jenkins-data目錄授權(quán),并重新加載nfs,如下所示。

#為/opt/nfs/jenkins-data/目錄授權(quán)chown -R 1000 /opt/nfs/jenkins-data/#重新加載nfs-serversystemctl reload nfs-server

在K8S集群中任意一個(gè)節(jié)點(diǎn)上使用如下命令進(jìn)行驗(yàn)證:

#查看nfs系統(tǒng)的目錄權(quán)限showmount -e NFS_IP

如果能夠看到 /opt/nfs/jenkins-data 就表示 ok 了。

具體如下所示。

[root@test10 ~]# showmount -e 192.168.0.10Export list for 192.168.0.10:/opt/nfs/jenkins-data 192.168.175.0/24[root@test11 ~]# showmount -e 192.168.0.10Export list for 192.168.0.10:/opt/nfs/jenkins-data 192.168.175.0/243.創(chuàng)建PV

Jenkins 其實(shí)只要加載對(duì)應(yīng)的目錄就可以讀取之前的數(shù)據(jù),但是由于 deployment 無(wú)法定義存儲(chǔ)卷,因此我們只能使用 StatefulSet。

首先創(chuàng)建 pv,pv 是給 StatefulSet 使用的,每次 StatefulSet 啟動(dòng)都會(huì)通過(guò) volumeClaimTemplates 這個(gè)模板去創(chuàng)建 pvc,因此必須得有 pv,才能供 pvc 綁定。

創(chuàng)建jenkins-pv.yaml文件,文件內(nèi)容如下所示。

apiVersion: v1kind: PersistentVolumemetadata: name: jenkinsspec: nfs: path: /opt/nfs/jenkins-data server: 192.168.0.10 accessModes: ['ReadWriteOnce'] capacity: storage: 1Ti

我這里給了 1T存儲(chǔ)空間,可以根據(jù)實(shí)際配置。

執(zhí)行如下命令創(chuàng)建pv。

kubectl apply -f jenkins-pv.yaml 4.創(chuàng)建serviceAccount

創(chuàng)建service account,因?yàn)?jenkins 后面需要能夠動(dòng)態(tài)創(chuàng)建 slave,因此它必須具備一些權(quán)限。

創(chuàng)建jenkins-service-account.yaml文件,文件內(nèi)容如下所示。

apiVersion: v1kind: ServiceAccountmetadata: name: jenkins---kind: RoleapiVersion: rbac.authorization.k8s.io/v1beta1metadata: name: jenkinsrules: - apiGroups: [''] resources: ['pods'] verbs: ['create', 'delete', 'get', 'list', 'patch', 'update', 'watch'] - apiGroups: [''] resources: ['pods/exec'] verbs: ['create', 'delete', 'get', 'list', 'patch', 'update', 'watch'] - apiGroups: [''] resources: ['pods/log'] verbs: ['get', 'list', 'watch'] - apiGroups: [''] resources: ['secrets'] verbs: ['get']---apiVersion: rbac.authorization.k8s.io/v1beta1kind: RoleBindingmetadata: name: jenkinsroleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: jenkinssubjects: - kind: ServiceAccount name: jenkins

上述配置中,創(chuàng)建了一個(gè) RoleBinding 和一個(gè) ServiceAccount,并且將 RoleBinding 的權(quán)限綁定到這個(gè)用戶(hù)上。所以,jenkins 容器必須使用這個(gè) ServiceAccount 運(yùn)行才行,不然 RoleBinding 的權(quán)限它將不具備。

RoleBinding 的權(quán)限很容易就看懂了,因?yàn)?jenkins 需要?jiǎng)?chuàng)建和刪除 slave,所以才需要上面這些權(quán)限。至于 secrets 權(quán)限,則是 https 證書(shū)。

執(zhí)行如下命令創(chuàng)建serviceAccount。

kubectl apply -f jenkins-service-account.yaml 5.安裝Jenkins

創(chuàng)建jenkins-statefulset.yaml文件,文件內(nèi)容如下所示。

apiVersion: apps/v1kind: StatefulSetmetadata: name: jenkins labels: name: jenkinsspec: selector: matchLabels: name: jenkins serviceName: jenkins replicas: 1 updateStrategy: type: RollingUpdate template: metadata: name: jenkins labels:name: jenkins spec: terminationGracePeriodSeconds: 10 serviceAccountName: jenkins containers:- name: jenkins image: docker.io/jenkins/jenkins:lts imagePullPolicy: IfNotPresent ports: - containerPort: 8080 - containerPort: 32100 resources: limits: cpu: 4 memory: 4Gi requests: cpu: 4 memory: 4Gi env: - name: LIMITS_MEMORY valueFrom:resourceFieldRef: resource: limits.memory divisor: 1Mi - name: JAVA_OPTS # value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -XshowSettings:vm -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85 value: -Xmx$(LIMITS_MEMORY)m -XshowSettings:vm -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85 volumeMounts: - name: jenkins-home mountPath: /var/jenkins_home livenessProbe: httpGet: path: /login port: 8080 initialDelaySeconds: 60 timeoutSeconds: 5 failureThreshold: 12 # ~2 minutes readinessProbe: httpGet: path: /login port: 8080 initialDelaySeconds: 60 timeoutSeconds: 5 failureThreshold: 12 # ~2 minutes # pvc 模板,對(duì)應(yīng)之前的 pv volumeClaimTemplates: - metadata:name: jenkins-home spec:accessModes: ['ReadWriteOnce']resources: requests: storage: 1Ti

jenkins 部署時(shí)需要注意它的副本數(shù),你的副本數(shù)有多少就要有多少個(gè) pv,同樣,存儲(chǔ)會(huì)有多倍消耗。這里我只使用了一個(gè)副本,因此前面也只創(chuàng)建了一個(gè) pv。

使用如下命令安裝Jenkins。

kubectl apply -f jenkins-statefulset.yaml 6.創(chuàng)建Service

創(chuàng)建jenkins-service.yaml文件,主要用于后臺(tái)運(yùn)行Jenkins,文件內(nèi)容如下所示。

apiVersion: v1kind: Servicemetadata: name: jenkinsspec: # type: LoadBalancer selector: name: jenkins # ensure the client ip is propagated to avoid the invalid crumb issue when using LoadBalancer (k8s >=1.7) #externalTrafficPolicy: Local ports: - name: http port: 80 nodePort: 31888 targetPort: 8080 protocol: TCP - name: jenkins-agent port: 32100 nodePort: 32100 targetPort: 32100 protocol: TCP type: NodePort

使用如下命令安裝Service。

kubectl apply -f jenkins-service.yaml 7.安裝 ingress

jenkins 的 web 界面需要從集群外訪(fǎng)問(wèn),這里我們選擇的是使用 ingress。創(chuàng)建jenkins-ingress.yaml文件,文件內(nèi)容如下所示。

apiVersion: extensions/v1beta1kind: Ingressmetadata: name: jenkinsspec: rules: - http:paths: - path: / backend: serviceName: jenkins servicePort: 31888 host: jekins.binghe.com

這里,需要注意的是host必須配置為域名或者主機(jī)名,否則會(huì)報(bào)錯(cuò),如下所示。

The Ingress 'jenkins' is invalid: spec.rules[0].host: Invalid value: '192.168.0.10': must be a DNS name, not an IP address

使用如下命令安裝ingress。

kubectl apply -f jenkins-ingress.yaml

最后,由于我這里使用的是虛擬機(jī)來(lái)搭建相關(guān)的環(huán)境,在本機(jī)訪(fǎng)問(wèn)虛擬機(jī)映射的jekins.binghe.com時(shí),需要配置本機(jī)的hosts文件,在本機(jī)的hosts文件中加入如下配置項(xiàng)。

192.168.0.10 jekins.binghe.com

注意:在Windows操作系統(tǒng)中,hosts文件所在的目錄如下。

C:WindowsSystem32driversetc

接下來(lái),就可以在瀏覽器中通過(guò)鏈接:http://jekins.binghe.com:31888 來(lái)訪(fǎng)問(wèn)Jekins了。

物理機(jī)安裝SVN

Apache Subversion 通常被縮寫(xiě)成 SVN,是一個(gè)開(kāi)放源代碼的版本控制系統(tǒng),Subversion 在 2000 年由 CollabNet Inc 開(kāi)發(fā),現(xiàn)在發(fā)展成為 Apache 軟件基金會(huì)的一個(gè)項(xiàng)目,同樣是一個(gè)豐富的開(kāi)發(fā)者和用戶(hù)社區(qū)的一部分。

SVN相對(duì)于的RCS、CVS,采用了分支管理系統(tǒng),它的設(shè)計(jì)目標(biāo)就是取代CVS。互聯(lián)網(wǎng)上免費(fèi)的版本控制服務(wù)多基于Subversion。

這里,以在Master節(jié)點(diǎn)(binghe101服務(wù)器)上安裝SVN為例。

1.使用yum安裝SVN

在命令行執(zhí)行如下命令安裝SVN。

yum -y install subversion 2.創(chuàng)建SVN庫(kù)

依次執(zhí)行如下命令。

#創(chuàng)建/data/svnmkdir -p /data/svn #初始化svnsvnserve -d -r /data/svn#創(chuàng)建代碼倉(cāng)庫(kù)svnadmin create /data/svn/test3.配置SVN

mkdir /data/svn/confcp /data/svn/test/conf/* /data/svn/conf/cd /data/svn/conf/[root@binghe101 conf]# ll總用量 20-rw-r--r-- 1 root root 1080 5月 12 02:17 authz-rw-r--r-- 1 root root 885 5月 12 02:17 hooks-env.tmpl-rw-r--r-- 1 root root 309 5月 12 02:17 passwd-rw-r--r-- 1 root root 4375 5月 12 02:17 svnserve.conf

配置authz文件,

vim authz

配置后的內(nèi)容如下所示。

[aliases]# joe = /C=XZ/ST=Dessert/L=Snake City/O=Snake Oil, Ltd./OU=Research Institute/CN=Joe Average[groups]# harry_and_sally = harry,sally# harry_sally_and_joe = harry,sally,&joeSuperAdmin = adminbinghe = admin,binghe# [/foo/bar]# harry = rw# &joe = r# * =# [repository:/baz/fuz]# @harry_and_sally = rw# * = r[test:/]@SuperAdmin=rw@binghe=rw

配置passwd文件

vim passwd

配置后的內(nèi)容如下所示。

[users]# harry = harryssecret# sally = sallyssecretadmin = admin123binghe = binghe123

配置 svnserve.conf

vim svnserve.conf

配置后的文件如下所示。

### This file controls the configuration of the svnserve daemon, if you### use it to allow access to this repository. (If you only allow### access through http: and/or file: URLs, then this file is### irrelevant.)### Visit http://subversion.apache.org/ for more information.[general]### The anon-access and auth-access options control access to the### repository for unauthenticated (a.k.a. anonymous) users and### authenticated users, respectively.### Valid values are 'write', 'read', and 'none'.### Setting the value to 'none' prohibits both reading and writing;### 'read' allows read-only access, and 'write' allows complete ### read/write access to the repository.### The sample settings below are the defaults and specify that anonymous### users have read-only access to the repository, while authenticated### users have read and write access to the repository.anon-access = noneauth-access = write### The password-db option controls the location of the password### database file. Unless you specify a path starting with a /,### the file’s location is relative to the directory containing### this configuration file.### If SASL is enabled (see below), this file will NOT be used.### Uncomment the line below to use the default password file.password-db = /data/svn/conf/passwd### The authz-db option controls the location of the authorization### rules for path-based access control. Unless you specify a path### starting with a /, the file’s location is relative to the### directory containing this file. The specified path may be a### repository relative URL (^/) or an absolute file:// URL to a text### file in a Subversion repository. If you don’t specify an authz-db,### no path-based access control is done.### Uncomment the line below to use the default authorization file.authz-db = /data/svn/conf/authz### The groups-db option controls the location of the file with the### group definitions and allows maintaining groups separately from the### authorization rules. The groups-db file is of the same format as the### authz-db file and should contain a single [groups] section with the### group definitions. If the option is enabled, the authz-db file cannot### contain a [groups] section. Unless you specify a path starting with### a /, the file’s location is relative to the directory containing this### file. The specified path may be a repository relative URL (^/) or an### absolute file:// URL to a text file in a Subversion repository.### This option is not being used by default.# groups-db = groups### This option specifies the authentication realm of the repository.### If two repositories have the same authentication realm, they should### have the same password database, and vice versa. The default realm### is repository’s uuid.realm = svn### The force-username-case option causes svnserve to case-normalize### usernames before comparing them against the authorization rules in the### authz-db file configured above. Valid values are 'upper' (to upper-### case the usernames), 'lower' (to lowercase the usernames), and### 'none' (to compare usernames as-is without case conversion, which### is the default behavior).# force-username-case = none### The hooks-env options specifies a path to the hook script environment ### configuration file. This option overrides the per-repository default### and can be used to configure the hook script environment for multiple ### repositories in a single file, if an absolute path is specified.### Unless you specify an absolute path, the file’s location is relative### to the directory containing this file.# hooks-env = hooks-env[sasl]### This option specifies whether you want to use the Cyrus SASL### library for authentication. Default is false.### Enabling this option requires svnserve to have been built with Cyrus### SASL support; to check, run ’svnserve --version’ and look for a line### reading ’Cyrus SASL authentication is available.’# use-sasl = true### These options specify the desired strength of the security layer### that you want SASL to provide. 0 means no encryption, 1 means### integrity-checking only, values larger than 1 are correlated### to the effective key length for encryption (e.g. 128 means 128-bit### encryption). The values below are the defaults.# min-encryption = 0# max-encryption = 256

接下來(lái),將/data/svn/conf目錄下的svnserve.conf文件復(fù)制到/data/svn/test/conf/目錄下。如下所示。

[root@binghe101 conf]# cp /data/svn/conf/svnserve.conf /data/svn/test/conf/cp:是否覆蓋’/data/svn/test/conf/svnserve.conf’? y4.啟動(dòng)SVN服務(wù)

(1)創(chuàng)建svnserve.service服務(wù)

創(chuàng)建svnserve.service文件

vim /usr/lib/systemd/system/svnserve.service

文件的內(nèi)

標(biāo)簽: Docker
相關(guān)文章:
主站蜘蛛池模板: 草久在线视频 | 中文二区| 日韩成人精品在线 | 日韩不卡一区二区三区 | 成人a级片在线观看 | 日韩精品中文字幕一区二区三区 | 久久久成人网 | 超级碰在线视频 | 国产精品无码久久久久 | 蜜臀久久99精品久久久无需会员 | 日韩亚洲在线 | 91精品久久久久久9s密挑 | 亚洲女人天堂成人av在线 | 日韩视频国产 | 狠狠搞狠狠干 | 国产传媒毛片精品视频第一次 | 国产黄色在线免费看 | 欧美激情在线精品一区二区三区 | av三级| 欧洲一区二区三区 | 日本福利视频网 | 中文字幕一区二区三区乱码图片 | 99久久久成人国产精品 | 毛片免费看 | 欧洲尺码日本国产精品 | 色婷婷综合网 | 中文字幕在线导航 | 亚洲精品wwww| 久久久蜜桃 | 国产亚洲视频在线 | 亚洲一区二区三区四区五区中文 | 欧美韩国日本一区 | 99精品热| 国产在线二区 | 日韩视频免费在线观看 | 在线观看成人av | 国产欧美久久一区二区三区 | 日韩欧洲亚洲 | 四色成人av永久网址 | 九九热这里都是精品 | 精品久久av| 99视频在线看 | 性人久久久 | 国产激情影院 | 先锋av资源在线 | 日本免费在线 | 日日爱夜夜操 | 久久精品一区二区三区四区 | 久久久xx | 午夜爽| 91黄色免费看 | 亚洲免费一区 | 欧洲一区在线 | 在线日韩中文字幕 | 啊v在线 | 日韩av免费在线观看 | 久久精品美女 | 狠狠伊人 | 毛片久久 | 99re热精品视频 | 日韩一区免费在线观看 | 狠狠狠干 | 欧美激情在线精品一区二区三区 | 青青草亚洲 | 欧洲亚洲精品久久久久 | 国产最新精品视频 | 午夜视频在线观看网站 | 美女视频一区二区三区 | 伊人一区 | 永久91嫩草亚洲精品人人 | 久久精品亚洲精品国产欧美 | 亚洲精品二三区 | 久久影音先锋 | 国内精品一区二区三区视频 | 久久久久久久99精品免费观看 | 日韩高清成人 | 欧产日产国产精品一二 | 99re在线| 免费日韩视频 | 99精品欧美一区二区三区 | 欧美激情性国产欧美无遮挡 | 羞羞的视频在线免费观看 | 免费成人av | 神马久久久久久久久久 | 久久成人综合网 | 精品久久久免费视频 | 日韩精品 电影一区 亚洲 | 国产精品国产精品国产专区不蜜 | 免费黄色小片 | 欧美成人高清视频 | 国产欧美精品 | 天天天综合网 | 欧美成年黄网站色视频 | 91久久精品国产91久久 | 国产精品久久久久久一区二区三区 | 色综合天天天天做夜夜夜夜做 | 最新av网址大全 | 999精品视频 | 一级黄色av片 | 久久精品1| 久久亚洲天堂 | 91在线精品一区二区 | 国产精品久久久久久一级毛片 | 国产午夜精品视频 | 日韩欧美一级精品久久 | 日韩欧美网址 | 成人精品视频99在线观看免费 | 欧洲成人午夜免费大片 | 日韩精品91爱爱 | 国产精品女人视频 | 国产精品精品视频一区二区三区 | 成人免费crm在线观看 | 综合亚洲精品 | 久久精品免费一区二区三区 | 久久999免费视频 | 欧美亚洲国产一区 | 久久精品免费观看 | 亚洲日日操 | 亚洲国产精品一区二区久久,亚洲午夜 | 日韩精品一区二区三区四区 | 日韩欧美成人影院 | 婷婷综合五月 | 成人精品一区二区三区中文字幕 | 国产亚洲精品久久久久久久久 | 免费国产一区 | 欧美视频免费在线观看 | 天天天天干 | 久久99这里只有精品 | 99久久精品国产毛片 | 国内精品国产三级国产在线专 | 日韩欧美在线一区二区 | 国产精品视频一区二区三区不卡 | 毛片免费观看网址 | 青娱乐网站 | 亚洲高清在线观看 | 国产在线观看一区 | 欧美激情综合五月色丁香小说 | 黄色av网站在线免费观看 | 亚洲视频在线免费观看 | 久久久久久久国产 | 婷婷综合激情 | 亚洲福利片 | 日韩一区二区三区在线视频 | 成人国产免费视频 | 国产在线精品一区二区三区 | 欧美一区二区三区四区视频 | www视频在线观看 | 免费日韩 | 国产第一页在线播放 | 91高清视频在线观看 | 欧美国产日韩一区 | 91天天综合 | 亚洲区在线 | 欧美日韩一区二区三区在线观看 | 精品免费国产一区二区三区 | 亚洲高清视频在线 | 久草热视频| 国产一级片一区二区三区 | 中国大陆高清aⅴ毛片 | 亚洲天天操 | 欧美一区二区三区在线视频 | 2019天天操 | 久久精品国产一区二区三 | 亚洲精品乱码久久久久久久久 | 亚洲精品乱码久久久久久 | 伊人91| 91久久 | 免费不卡视频 | 欧美日韩黄色一级片 | 在线永久免费观看日韩a | 91久久91久久精品免观看 | 中文字幕在线看 | www.五月婷婷 | 激情视频在线观看 | 一级黄色毛片免费观看 | 成人a在线视频 | 日本黄a三级三级三级 | 国产精品久久电影观看 | av中文字幕在线观看 | 蜜桃视频在线观看www社区 | 毛片视频免费 | 日韩欧美国产成人一区二区 | 视频一区二区三区在线观看 | 成人日韩| 在线三级电影 | 在线中文av | 欧美日韩中文国产一区发布 | 日韩免费一区 | 国精日本亚洲欧州国产中文久久 | 日精品 | 亚洲成av人片一区二区梦乃 | 欧美日韩成人在线播放 | 视频一区二区三区在线播放 | 欧美不卡视频一区发布 | 亚洲成人精品久久久 | 丁香午夜 | 日韩在线播 | 国产一区二区在线电影 | 一二三四在线视频观看社区 | 日韩精品| 丝袜久久 | 亚洲欧洲精品一区二区 | 亚洲国产精品一区二区久久 | 国产精品1区2区3区 欧美 中文字幕 | 人干人人 | 亚洲精品国产偷自在线观看 | 深夜福利1000 | 日本免费一区二区三区 | 亚洲精品乱码久久久久膏 | 欧美日韩精品网站 | 久久av一区二区三区 | 亚洲美女一区 | 国产婷婷综合 | 亚洲综合一区二区 | 精品久久久久国产 | 97伦理网 | av一区二区三区 | 中文字幕第十二页 | 国产精品久久久久不卡 | 久久精品一区二区三区四区 | 日干夜操 | 亚洲欧美视频一区 | 亚洲欧洲一区二区 | 中文字幕 国产精品 | 亚洲免费不卡视频 | 欧美日本韩国一区二区 | 欧美不卡 | 视频精品一区 | 亚洲一区精品在线 | 亚洲精品中文字幕在线观看 | 在线亚洲免费 | 操操操av | 超碰天堂 | 国产精品一品二区三区的使用体验 | 久久久av| 亚洲网站免费 | 欧美日韩国产高清视频 | 日批的视频| www.888www看片| 亚洲高清免费视频 | 国产精品久久7777 | 亚洲一级视频在线 | 精品三级在线观看 | 中文字幕久久久 | 精品国产一区二区三区性色av | 欧美日韩精品 | 一级免费视频 | 日韩视频免费在线 | 一区二区三区国产好的精 | 男女视频在线 | 成人免费av | 91国内外精品自在线播放 | 日韩成人在线电影 | 国产日韩一区 | 国产三级视频 | 亚洲av毛片一级二级在线 | 国产黄色影视 | 亚洲精品成人av | 91精品国产一区二区三区四区在线 | 日韩欧美一区二区视频 | 国产精品视频一区二区三区 | 亚洲国产成人91精品 | 精品无码久久久久久国产 | 91久久国产 | 久久久久久亚洲 | 美女二区 | 欧美日韩精品一区二区三区 | 一级全黄少妇性色生活片免费 | h视频网站在线 | 久久中文字幕一区二区 | 一级毛片视频 | 91精品国产91久久久久久蜜臀 | 黄色国产| 欧美一级免费 | 黄色一级视 | 国产精品第一区第27页 | 久久精品国产99国产精2020新增功能 | 视频一区二区国产 | 日韩精品一区二区三区视频播放 | 亚洲一区电影 | 在线一区二区三区做爰视频网站 | 欧美激情一区二区三区四区 | 欧美成人综合视频 | 国产婷婷 | 2020国产在线| 龙珠z普通话国语版在线观看 | 欧美日韩在线不卡 | 国产成人精品一区二区三区视频 | 天天干人人插 | 人人射人人插 | 一区二区三区精品 | 亚洲午夜精品视频 | 97精品国产97久久久久久粉红 | 精品国产不卡一区二区三区 | 国产精品一区二区在线观看 | 麻豆久久 | 色小妹三区| wwwsihu| 欧美日本一区二区三区 | a免费在线 | 中文字幕在线观看 | 中文字幕在线观看一区二区三区 | 国产精品成人在线观看 | 成人午夜视频在线 | 日韩亚洲视频在线观看 | 99草视频| 日韩中文字幕一区 | 久久精品免费视频观看 | 国产精品毛片在线 | 夜夜骑天天操 | 99久久免费精品国产男女性高好 | 婷婷av在线 | segui88久久综合9999 | 亚欧洲精品视频在线观看 | 午夜精 | 91精品久久久久久久久久小网站 | 性视频网| 在线成人av | 国产区视频 | 毛片网站在线观看 | 视频一区二区国产 | 亚洲精品久久久久久动漫 | 国产精品久久久久一区二区三区 | 欧洲毛片 | 国产成人aaa| 国产伦精品一区二区三区四区视频 | 超碰国产一区 | www在线视频| 久久久激情视频 | 日韩欧美在线一区二区 | 国产精品一区在线看 | 国产免费一区二区三区 | 久久蜜桃av一区二区天堂 | 91精品久久久久久久久 | 国产乱淫av片 | 国产成人精品午夜视频免费 | 婷婷在线视频 | av成人在线观看 | 91精品电影 | 成年人免费看 | 久在线| 女人色网 | 亚洲精品欧美视频 | 日韩欧美在线视频 | 亚洲国产精品成人 | 亚洲成人中文字幕 | 国产精品久久精品 | 亚洲男人天堂2023 | 91精品久久久久久久久久 | 国产精品国产三级国产aⅴ原创 | 欧美一级免费看 | 欧美成人精品一区二区三区 | 精品亚洲一区二区三区 | 国产老女人精品毛片久久 | 欧美日韩高清一区 | 国外成人在线视频 | 亚洲欧洲无码一区二区三区 | 综合 欧美 亚洲日本 | 久久在线视频 | 日韩中文在线视频 | 日韩有码电影 | 在线成人av| 欧美日韩中文 | 久久免费视频3 | 亚洲午夜精品a | 成人免费在线电影 | 玖玖精品| 国产成人在线免费观看视频 | 成人影院av | 亚洲一区二区三区在线播放 | 国产亚洲精品美女久久久久久久久久 | 免费黄色av| av中文字幕在线播放 | 狠狠色综合色综合网络 | 天堂国产 | 午夜网址 | 久久久久久91亚洲精品中文字幕 | 成人免费视频观看视频 | 色综合99 | 国产激情视频在线观看 | 四虎5151久久欧美毛片 | 国产精品久久免费观看spa | 激情网页| 日韩成人精品在线 | 国产精品久久久久久福利一牛影视 | 国产精品久久久久久久久免费桃花 | 国产一区二区影院 | 亚洲视频一区 | 视频专区一区二区 | 免费在线精品视频 | 日本黄色a视频 | 高清av网站 | 在线观看国产视频 | 日韩精品在线观看免费 | 国产免费拔擦拔擦8x高清在线人 | 欧美成人一区二区三区片免费 | 国产视频亚洲精品 | 亚州中文字幕 | 一区二区三区免费网站 | 青青久久| 91夜夜蜜桃臀一区二区三区 | 毛片一区二区 | jizz在亚洲| 国产一区二区免费 | 欧美一区二区三 | 久久高潮 | 午夜激情影院 | 中文字幕一区二区三 | 成人黄色在线视频 | 亚洲婷婷一区 | 国产精品久久久久久久粉嫩 | 成人久久精品 | 国产一区二区三区四区在线观看 | 国产视频中文字幕 | 91精品久久 | 精品美女久久久 | 夜夜草视频 | 在线观看亚洲专区 | 男女视频在线观看 | 成人羞羞在线观看网站 | 大陆一级毛片免费视频观看 | 黄色欧美一级片 | 蜜桃视频在线播放 | 欧美激情视频一区二区三区在线播放 | 国产在线不卡 | 新91在线视频 | 欧美性猛交一区二区三区精品 | 狠狠色综合色综合网络 | 成人精品视频 | 一级黄色片看看 | 一级黄色大片免费 | 狠狠的日| 国产高清在线精品一区二区三区 | 久久精品99国产精品亚洲最刺激 | 国产日韩欧美综合 | 欧洲另类二三四区 | 国产精品毛片一区二区三区 | 国产在线一级视频 | 国产日韩欧美一区 | 精品一区二区视频 | 亚洲精品国产第一综合99久久 | 欧洲精品一区二区 | 亚洲国产成人av | 国产精品视频99 | 欧美综合一区二区 | 免费毛片网 | 在线视频一二区 | 99久久婷婷国产综合精品 | 中文字幕日韩专区 | 日韩成人影院 | 久久精品国产精品青草 | 日韩福利视频导航 | 男女羞羞羞视频午夜视频 | 毛片在线网站 | 欧美大片网站 | 成人在线看片 | av在线一区二区三区 | av成人免费 | 亚洲高清视频在线 | 日韩欧美在线观看视频网站 | 精品无人乱码一区二区三区 | 亚洲毛片在线 | 一区欧美 | 国产精品久久久久久久久久久久久久 | 亚洲精品91 | 国产激情精品视频 | 亚洲精品视频在线看 | 久久二区三区 | 一 级 黄 色 片免费网站 | 精品视频免费观看 | 久久精品国产91精品亚洲高清 | 国产精品永久免费 | 亚洲婷婷综合网 | 亚洲一区在线免费观看 | 日韩爱爱视频 | 亚洲乱码在线 | 久久精品免费一区二区 | 黄视频网站免费观看 | 亚洲一区国产视频 | 日韩中文字幕一区二区 | 精品三区在线观看 | 天堂网色| 毛片免费网站 | 精品一区免费 | 欧美日韩在线一区二区 | 夜夜操com| www.日韩| 在线视频这里只有精品 | 2012中文版免费观看 | 亚洲精品综合 | 婷婷桃色网 | 成人av播放 | 狠狠干天天干 | 成人激情视频在线观看 | 欧美成人免费 | 亚洲一区二区伦理 | 欧美亚洲天堂 | 久久手机免费视频 | 久久精品日| 天天干天天插 | 美女超碰 | 国产免费久久 | 欧美精品久 | 91麻豆精品国产91久久久久久久久 | 亚洲免费观看视频 | 日韩高清成人 | 波多野结衣一区三区 | 亚洲成人一区二区三区 | 午夜亚洲福利 | 欧美精品一区二区三区四区 | 日韩免费视频 | 秋霞av电影| 久久精品国产99精品国产亚洲性色 | 久久蜜桃精品一区二区三区综合网 | 国产成人高清在线 | 黄色a级网站 | 欧美精品成人一区二区三区四区 | 国产精品一区二区三区四区五区 | 亚洲成人av在线 | 欧美视频精品 | 久久精品久久久久久久久久16 | av高清在线免费观看 | 久久99精品国产麻豆婷婷洗澡 | 成人在线国产 | 亚洲免费在线观看 | 视频一区免费观看 | 免费在线色 | 日本超碰 | 色av一区 | 四虎影视网址 | 一区二区在线播放视频 | 午夜一级毛片 | 免费视频爱爱太爽了 | 久久亚洲综合 | 国产精品一二三区 | 久久婷婷国产麻豆91天堂 | 一区二区三区精品 | 在线免费观看黄 | 日韩久久精品 | 久久都是精品 | 男女网站在线观看 | 中文字幕色 | 久久99精品国产麻豆婷婷洗澡 | 午夜精品一区 | 亚洲av毛片一区二二区三三区 | 欧美中文在线 | 久久久艹 | 国产精品a一区二区三区网址 | 亚洲怡红院在线观看 | 无码一区二区三区视频 | 亚洲毛片 | 99国产精品久久久久久久 | 欧美一级视频免费 | 日本高清视频在线播放 | 国产精品一区一区 | av在线播放网址 | 亚洲午夜精品一区二区三区他趣 | 欧美色阁| 成年人视频在线观看免费 | 国产视频一区二区 | 久久久久久久久久久精 | 亚洲精品91 | 在线一级视频 | 香蕉久久一区二区不卡无毒影院 | 日本黄色影片在线观看 | 国产亚洲一区二区三区在线观看 | 免费毛片网 | 国产在线中文字幕 | 亚洲国产成人av好男人在线观看 | 成人免费看 | 黄毛片网站 | 久久白虎 | 欧美一级二级三级 | 在线观看91视频 | 欧美视频一区 | 在线欧美亚洲 | 在线观看一区二区三区四区 | 国产黄视频在线 | 精品视频久久久 | 久久亚洲二区 | 成人网av | 国精产品99永久一区一区 | 电影91久久久 | 国产精品国产 | 狠狠综合 | 亚洲色图p | 亚洲人成在线观看 | 欧美一区 | 亚洲一区二区福利 | 成人av观看 | 久久福利电影 | 免费av黄色| 成人欧美一区二区三区黑人孕妇 | 亚洲国产99 | 99pao成人国产永久免费视频 | www中文字幕 | 青草福利| 婷婷色国产偷v国产偷v小说 | 狠狠躁夜夜躁人人爽天天高潮 | 国产精品久久久久久亚洲调教 | 毛片在线视频 | 一本一道久久a久久精品综合蜜臀 | 久久久av | 久久这里只有精品8 | 国产小视频在线播放 | 欧美一级片在线观看 | 99精品国产热久久91蜜凸 | 欧美日韩中文在线 | 国产精品揄拍一区二区久久国内亚洲精 | 午夜久久网站 | 99草在线视频 | 97色综合 | 国产精品久久久久久久久久久久冷 | 中文字幕国产视频 | 日韩在线成人 |