基于Docker+K8S+GitLab/SVN+Jenkins+Harbor搭建持續(xù)集成交付環(huán)境的詳細(xì)教程
環(huán)境搭建概述
親愛的家人們可以到鏈接:http://xiazai.jb51.net/202105/yuanma/javayaml_jb51.rar 下載所需要的yaml文件。
1.K8S是什么?
K8S全稱是Kubernetes,是一個(gè)全新的基于容器技術(shù)的分布式架構(gòu)領(lǐng)先方案,基于容器技術(shù),目的是實(shí)現(xiàn)資源管理的自動化,以及跨多個(gè)數(shù)據(jù)中心的資源利用率的最大化。
如果我們的系統(tǒng)設(shè)計(jì)遵循了kubernetes的設(shè)計(jì)思想,那么傳統(tǒng)系統(tǒng)架構(gòu)中那些和業(yè)務(wù)沒有多大關(guān)系的底層代碼或功能模塊,都可以使用K8S來管理,我們不必再費(fèi)心于負(fù)載均衡的選型和部署實(shí)施問題,不必再考慮引入或自己開發(fā)一個(gè)復(fù)雜的服務(wù)治理框架,不必再頭疼與服務(wù)監(jiān)控和故障處理模塊的開發(fā)??傊褂胟ubernetes提供的解決方案,會大大減少開發(fā)成本,同時(shí)可以將精力更加集中于業(yè)務(wù)本身,而且由于kubernetes提供了強(qiá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)解決方案??梢灶A(yù)見,在未來幾年內(nèi),會有大量的新系統(tǒng)選擇它,不管是運(yùn)行在企業(yè)本地服務(wù)器上還是被托管到公有云上。
3.使用K8S有哪些好處?
使用Kubernetes就是在全面部署微服務(wù)架構(gòu)。微服務(wù)架構(gòu)的核心就是將一個(gè)巨大的單體應(yīng)用分解為很多小的互相連接的微服務(wù),一個(gè)微服務(wù)背后可能有多個(gè)實(shí)例副本在支撐,副本的數(shù)量可能會隨著系統(tǒng)的負(fù)荷變化而進(jìn)行調(diào)整,內(nèi)嵌的負(fù)載均衡器在 k8s 平臺中有多個(gè)實(shí)例副本在支撐,副本的數(shù)量可能會隨著系統(tǒng)的負(fù)荷變化而進(jìn)行調(diào)整,內(nèi)嵌的負(fù)載均衡器 在k8s 平臺中發(fā)揮了重要的作用。微服務(wù)架構(gòu)使得每個(gè)服務(wù)都可以由專門的開發(fā)團(tuán)隊(duì)來開發(fā),開發(fā)者可以自由選擇開發(fā)技術(shù),這對于大規(guī)模團(tuán)隊(duì)來說很有價(jià)值。另外,每個(gè)微服務(wù)獨(dú)立開發(fā)、升級、擴(kuò)展,使得系統(tǒng)具備很高的穩(wěn)定性和快速迭代進(jìn)化能力。
4.環(huán)境構(gòu)成
整套環(huán)境的搭建包含:Docker環(huán)境的搭建、docker-compose環(huán)境的搭建、K8S集群的搭建、GitLab代碼倉庫的搭建、SVN倉庫的搭建、Jenkins自動化部署環(huán)境的搭建、Harbor私有倉庫的搭建。
本文檔中,整套環(huán)境的搭建包括:
- 安裝Docker環(huán)境
- 安裝docker-compose
- 安裝K8S集群環(huán)境
- 重啟K8S集群引起的問題
- K8S安裝ingress-nginx
- K8S安裝gitlab代碼倉庫
- 安裝Harbor私有倉庫
- 安裝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)境
| 軟件名稱 | 軟件版本 | 說明 |
|---|---|---|
| Docker | 19.03.8 | 提供容器環(huán)境 |
| docker-compose | 1.25.5 | 定義和運(yùn)行由多個(gè)容器組成的應(yīng)用 |
| K8S | 1.18.2 | 是一個(gè)開源的,用于管理云平臺中多個(gè)主機(jī)上的容器化的應(yīng)用,Kubernetes的目標(biāo)是讓部署容器化的應(yīng)用簡單并且高效(powerful),Kubernetes提供了應(yīng)用部署,規(guī)劃,更新,維護(hù)的一種機(jī)制。 |
| GitLab | 12.1.6 | 代碼倉庫 |
| Harbor | 1.10.2 | 私有鏡像倉庫 |
| Jenkins | 2.222.3 | 持續(xù)集成交付 |
安裝Docker環(huán)境
Docker 是一個(gè)開源的應(yīng)用容器引擎,基于 Go 語言 并遵從 Apache2.0 協(xié)議開源。
Docker 可以讓開發(fā)者打包他們的應(yīng)用以及依賴包到一個(gè)輕量級、可移植的容器中,然后發(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開機(jī)啟動 systemctl enable docker.service #啟動Docker systemctl start docker.service #查看Docker版本 docker version
在每臺服務(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)用程序的工具。通過 Compose,您可以使用 YML 文件來配置應(yīng)用程序需要的所有服務(wù)。然后,使用一個(gè)命令,就可以從 YML 文件配置中創(chuàng)建并啟動所有服務(wù)。
注意:在每臺服務(wù)器上安裝docker-compose
1.下載docker-compose文件
#下載并安裝docker-compose curl -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-compose
3.查看docker-compose版本
#查看docker-compose版本 [root@binghe ~]# docker-compose version docker-compose version 1.25.5, build 8a1c60f6 docker-py version: 4.1.0 CPython version: 3.7.5 OpenSSL version: OpenSSL 1.1.0l 10 Sep 2019
安裝K8S集群環(huán)境
Kubernetes是一個(gè)開源的,用于管理云平臺中多個(gè)主機(jī)上的容器化的應(yīng)用,Kubernetes的目標(biāo)是讓部署容器化的應(yīng)用簡單并且高效(powerful),Kubernetes提供了應(yīng)用部署,規(guī)劃,更新,維護(hù)的一種機(jī)制。
本文檔基于K8S 1.8.12版本來搭建K8S集群
安裝K8S基礎(chǔ)環(huán)境
在所有服務(wù)器上創(chuàng)建install_k8s.sh腳本文件,腳本文件的內(nèi)容如下所示。
#################配置阿里云鏡像加速器開始########################
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://zz3sblpi.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker
######################配置阿里云鏡像加速器結(jié)束#########################
#安裝nfs-utils
yum install -y nfs-utils
#安裝wget軟件下載命令
yum install -y wget
#啟動nfs-server
systemctl start nfs-server
#配置nfs-server開機(jī)自啟動
systemctl enable nfs-server
#關(guān)閉防火墻
systemctl stop firewalld
#取消防火墻開機(jī)自啟動
systemctl disable firewalld
#關(guān)閉SeLinux
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
# 關(guān)閉 swap
swapoff -a
yes | cp /etc/fstab /etc/fstab_bak
cat /etc/fstab_bak |grep -v swap > /etc/fstab
############################修改 /etc/sysctl.conf開始###########################
# 如果有配置,則修改
sed -i "s#^net.ipv4.ip_forward.*#net.ipv4.ip_forward=1#g" /etc/sysctl.conf
sed -i "s#^net.bridge.bridge-nf-call-ip6tables.*#net.bridge.bridge-nf-call-ip6tables=1#g" /etc/sysctl.conf
sed -i "s#^net.bridge.bridge-nf-call-iptables.*#net.bridge.bridge-nf-call-iptables=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.all.disable_ipv6.*#net.ipv6.conf.all.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.default.disable_ipv6.*#net.ipv6.conf.default.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.lo.disable_ipv6.*#net.ipv6.conf.lo.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.all.forwarding.*#net.ipv6.conf.all.forwarding=1#g" /etc/sysctl.conf
# 可能沒有,追加
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.default.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.conf
############################修改 /etc/sysctl.conf結(jié)束###########################
# 執(zhí)行命令使修改后的/etc/sysctl.conf文件生效
sysctl -p
################# 配置K8S的yum源開始#############################
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
################# 配置K8S的yum源結(jié)束#############################
# 卸載舊版本K8S
yum 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í)可能會碰到如下錯(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)定性
# 如果訪問 https://hub.docker.io 速度非常穩(wěn)定,也可以跳過這個(gè)步驟,一般不需配置
# curl -sSL https://kuboard.cn/install-script/set_mirror.sh | sh -s ${REGISTRY_MIRROR}
# 重新加載配置文件
systemctl daemon-reload
#重啟 docker
systemctl restart docker
# 將kubelet設(shè)置為開機(jī)啟動并啟動kubelet
systemctl enable kubelet && systemctl start kubelet
# 查看docker版本
docker version
在每臺服務(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)境
注意:下面的命令需要在命令行手動執(zhí)行。
# 只在 master 節(jié)點(diǎn)執(zhí)行
# export 命令只在當(dāng)前 shell 會話中有效,開啟新的 shell 窗口后,如果要繼續(xù)安裝過程,請重新執(zhí)行此處的 export 命令
export MASTER_IP=192.168.0.10
# 替換 k8s.master 為 您想要的 dnsName
export APISERVER_NAME=k8s.master
# Kubernetes 容器組所在的網(wǎng)段,該網(wǎng)段安裝完成后,由 kubernetes 創(chuàng)建,事先并不存在于物理網(wǎng)絡(luò)中
export POD_SUBNET=172.18.0.1/16
echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
2.初始化Master節(jié)點(diǎn)
在test10服務(wù)器上創(chuàng)建init_master.sh腳本文件,文件內(nèi)容如下所示。
#!/bin/bash
# 腳本出錯(cuò)時(shí)終止執(zhí)行
set -e
if [ ${#POD_SUBNET} -eq 0 ] || [ ${#APISERVER_NAME} -eq 0 ]; then
echo -e "\033[31;1m請確保您已經(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 1
fi
# 查看完整配置選項(xiàng) https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2
rm -f ./kubeadm-config.yaml
cat <<EOF > ./kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.18.2
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
controlPlaneEndpoint: "${APISERVER_NAME}:6443"
networking:
serviceSubnet: "10.96.0.0/16"
podSubnet: "${POD_SUBNET}"
dnsDomain: "cluster.local"
EOF
# kubeadm init
# 初始化kebeadm
kubeadm init --config=kubeadm-config.yaml --upload-certs
# 配置 kubectl
rm -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/onpremises
echo "安裝calico-3.13.1"
rm -f calico-3.13.1.yaml
wget https://kuboard.cn/install-script/calico/calico-3.13.1.yaml
kubectl 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.sh
3.查看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 wide Every 2.0s: kubectl get pod -n kube-system -o wide test10: Sun May 10 11:01:32 2020 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED 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 wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME test10 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-command W0510 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)
針對所有的 worker 節(jié)點(diǎn)執(zhí)行,在這里,就是在test11服務(wù)器和test12服務(wù)器上執(zhí)行。
在命令分別手動執(zhí)行如下命令。
# 只在 worker 節(jié)點(diǎn)執(zhí)行
# 192.168.0.10 為 master 節(jié)點(diǎn)的內(nèi)網(wǎng) IP
export MASTER_IP=192.168.0.10
# 替換 k8s.master 為初始化 master 節(jié)點(diǎn)時(shí)所使用的 APISERVER_NAME
export APISERVER_NAME=k8s.master
echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
# 替換為 master 節(jié)點(diǎn)上 kubeadm token create 命令輸出的join
kubeadm 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 nodes NAME STATUS ROLES AGE VERSION test10 Ready master 20m v1.18.2 test11 Ready <none> 2m46s v1.18.2 test12 Ready <none> 2m46s v1.18.2
注意:kubectl get nodes命令后面加上-o wide參數(shù)可以輸出更多的信息。
重啟K8S集群引起的問題
1.Worker節(jié)點(diǎn)故障不能啟動
Master 節(jié)點(diǎn)的 IP 地址發(fā)生變化,導(dǎo)致 worker 節(jié)點(diǎn)不能啟動。需要重新安裝K8S集群,并確保所有節(jié)點(diǎn)都有固定的內(nèi)網(wǎng) IP 地址。
2.Pod崩潰或不能正常訪問
重啟服務(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 作為替代,重新啟動的 Pod 通常能夠正常工作。
其中,pod-name表示運(yùn)行在K8S中的pod的名稱,pod-namespece表示命名空間。例如,需要?jiǎng)h除pod名稱為pod-test,命名空間為pod-test-namespace的pod,可以使用下面的命令。
kubectl delete pod pod-test -n pod-test-namespace
K8S安裝ingress-nginx
作為反向代理將外部流量導(dǎo)入集群內(nèi)部,將 Kubernetes 內(nèi)部的 Service 暴露給外部,在 Ingress 對象中通過域名匹配 Service,這樣就可以直接通過域名訪問到集群內(nèi)部的服務(wù)了。相對于 traefik 來說,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: v1
kind: Namespace
metadata:
name: ingress-nginx
labels:
name: ingress-nginx
執(zhí)行如下命令創(chuàng)建ingress-nginx命名空間。
kubectl apply -f ingress-nginx-namespace.yaml
2.安裝ingress controller
創(chuàng)建ingress-nginx-mandatory.yaml文件,主要的作用是安裝ingress-nginx。文件內(nèi)容如下所示。
apiVersion: v1
kind: Namespace
metadata:
name: ingress-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: default-http-backend
labels:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
namespace: ingress-nginx
spec:
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-backend
app.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: v1
kind: Service
metadata:
name: default-http-backend
namespace: ingress-nginx
labels:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
spec:
ports:
- port: 80
targetPort: 8080
selector:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-configuration
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: tcp-services
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: udp-services
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
apiVersion: v1
kind: ServiceAccount
metadata:
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/v1beta1
kind: ClusterRole
metadata:
name: nginx-ingress-clusterrole
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
rules:
- 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/v1beta1
kind: Role
metadata:
name: nginx-ingress-role
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
rules:
- 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/v1beta1
kind: RoleBinding
metadata:
name: nginx-ingress-role-nisa-binding
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: nginx-ingress-role
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: nginx-ingress-clusterrole-nisa-binding
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nginx-ingress-clusterrole
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: ingress-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-ingress-controller
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
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-nginx
app.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.yaml
3.安裝K8S SVC:ingress-nginx
主要是用來用于暴露pod:nginx-ingress-controller。
創(chuàng)建service-nodeport.yaml文件,文件內(nèi)容如下所示。
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
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.yaml
4.訪問K8S SVC:ingress-nginx
查看ingress-nginx命名空間的部署情況,如下所示。
[root@test10 k8s]# kubectl get pod -n ingress-nginx NAME READY STATUS RESTARTS AGE default-http-backend-796ddcd9b-vfmgn 1/1 Running 1 10h nginx-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 TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE default-http-backend ClusterIP 10.96.247.2 <none> 80/TCP 7m3s ingress-nginx NodePort 10.96.40.6 <none> 80:30080/TCP,443:30443/TCP 4m35s
所以,可以通過Master節(jié)點(diǎn)(test10服務(wù)器)的IP地址和30080端口號來訪問ingress-nginx,如下所示。
[root@test10 k8s]# curl 192.168.0.10:30080 default backend - 404
也可以在瀏覽器打開http://192.168.0.10:30080 來訪問ingress-nginx,如下所示。
K8S安裝gitlab代碼倉庫
GitLab是由GitLabInc.開發(fā),使用MIT許可證的基于網(wǎng)絡(luò)的Git倉庫管理工具,且具有Wiki和issue跟蹤功能。使用Git作為代碼管理工具,并在此基礎(chǔ)上搭建起來的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: v1
kind: Namespace
metadata:
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/v1
kind: Deployment
metadata:
name: redis
namespace: k8s-ops
labels:
name: redis
spec:
selector:
matchLabels:
name: redis
template:
metadata:
name: redis
labels:
name: redis
spec:
containers:
- name: redis
image: sameersbn/redis
imagePullPolicy: IfNotPresent
ports:
- name: redis
containerPort: 6379
volumeMounts:
- mountPath: /var/lib/redis
name: data
livenessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 30
timeoutSeconds: 5
readinessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 10
timeoutSeconds: 5
volumes:
- name: data
hostPath:
path: /data1/docker/xinsrv/redis
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: k8s-ops
labels:
name: redis
spec:
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/v1
kind: Deployment
metadata:
name: postgresql
namespace: k8s-ops
labels:
name: postgresql
spec:
selector:
matchLabels:
name: postgresql
template:
metadata:
name: postgresql
labels:
name: postgresql
spec:
containers:
- name: postgresql
image: sameersbn/postgresql
imagePullPolicy: IfNotPresent
env:
- name: DB_USER
value: gitlab
- name: DB_PASS
value: passw0rd
- name: DB_NAME
value: gitlab_production
- name: DB_EXTENSION
value: pg_trgm
ports:
- name: postgres
containerPort: 5432
volumeMounts:
- mountPath: /var/lib/postgresql
name: data
livenessProbe:
exec:
command:
- pg_isready
- -h
- localhost
- -U
- postgres
initialDelaySeconds: 30
timeoutSeconds: 5
readinessProbe:
exec:
command:
- pg_isready
- -h
- localhost
- -U
- postgres
initialDelaySeconds: 5
timeoutSeconds: 1
volumes:
- name: data
hostPath:
path: /data1/docker/xinsrv/postgresql
---
apiVersion: v1
kind: Service
metadata:
name: postgresql
namespace: k8s-ops
labels:
name: postgresql
spec:
ports:
- name: postgres
port: 5432
targetPort: postgres
selector:
name: postgresql
首先,執(zhí)行如下命令創(chuàng)建/data1/docker/xinsrv/postgresql目錄。
mkdir -p /data1/docker/xinsrv/postgresql
接下來,安裝gitlab-postgresql,如下所示。
kubectl apply -f gitlab-postgresql.yaml
4.安裝gitlab
(1)配置用戶名和密碼
首先,在命令行使用base64編碼為用戶名和密碼進(jìn)行轉(zhuǎn)碼,本示例中,使用的用戶名為admin,密碼為admin.1231
轉(zhuǎn)碼情況如下所示。
[root@test10 k8s]# echo -n 'admin' | base64 YWRtaW4= [root@test10 k8s]# echo -n 'admin.1231' | base64 YWRtaW4uMTIzMQ==
轉(zhuǎn)碼后的用戶名為:YWRtaW4= 密碼為:YWRtaW4uMTIzMQ==
也可以對base64編碼后的字符串解碼,例如,對密碼字符串解碼,如下所示。
[root@test10 k8s]# echo 'YWRtaW4uMTIzMQ==' | base64 --decode admin.1231
接下來,創(chuàng)建secret-gitlab.yaml文件,主要是用戶來配置GitLab的用戶名和密碼,文件內(nèi)容如下所示。
apiVersion: v1 kind: Secret metadata: namespace: k8s-ops name: git-user-pass type: Opaque data: username: YWRtaW4= password: YWRtaW4uMTIzMQ==
執(zhí)行配置文件的內(nèi)容,如下所示。
kubectl create -f ./secret-gitlab.yaml
(2)安裝GitLab
創(chuàng)建gitlab.yaml文件,文件的內(nèi)容如下所示。
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitlab
namespace: k8s-ops
labels:
name: gitlab
spec:
selector:
matchLabels:
name: gitlab
template:
metadata:
name: gitlab
labels:
name: gitlab
spec:
containers:
- name: gitlab
image: sameersbn/gitlab:12.1.6
imagePullPolicy: IfNotPresent
env:
- 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: 22
volumeMounts:
- mountPath: /home/git/data
name: data
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 180
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
timeoutSeconds: 1
volumes:
- name: data
hostPath:
path: /data1/docker/xinsrv/gitlab
---
apiVersion: v1
kind: Service
metadata:
name: gitlab
namespace: k8s-ops
labels:
name: gitlab
spec:
ports:
- name: http
port: 80
nodePort: 30088
- name: ssh
port: 22
targetPort: ssh
nodePort: 30022
type: NodePort
selector:
name: gitlab
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: gitlab
namespace: k8s-ops
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: gitlab.binghe.com
http:
paths:
- backend:
serviceName: gitlab
servicePort: http
注意:在配置GitLab時(shí),監(jiān)聽主機(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.yaml
5.安裝完成
查看k8s-ops命名空間部署情況,如下所示。
[root@test10 k8s]# kubectl get pod -n k8s-ops NAME READY STATUS RESTARTS AGE gitlab-7b459db47c-5vk6t 0/1 Running 0 11s postgresql-79567459d7-x52vx 1/1 Running 0 30m redis-67f4cdc96c-h5ckz 1/1 Running 1 10h
也可以使用如下命令查看。
[root@test10 k8s]# kubectl get pod --namespace=k8s-ops NAME READY STATUS RESTARTS AGE gitlab-7b459db47c-5vk6t 0/1 Running 0 36s postgresql-79567459d7-x52vx 1/1 Running 0 30m redis-67f4cdc96c-h5ckz 1/1 Running 1 10h
二者效果一樣。
接下來,查看GitLab的端口映射,如下所示。
[root@test10 k8s]# kubectl get svc -n k8s-ops NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gitlab NodePort 10.96.153.100 <none> 80:30088/TCP,22:30022/TCP 2m42s postgresql ClusterIP 10.96.203.119 <none> 5432/TCP 32m redis ClusterIP 10.96.107.150 <none> 6379/TCP 10h
此時(shí),可以看到,可以通過Master節(jié)點(diǎn)(test10)的主機(jī)名gitlab.binghe.com和端口30088就能夠訪問GitLab。由于我這里使用的是虛擬機(jī)來搭建相關(guān)的環(huán)境,在本機(jī)訪問虛擬機(jī)映射的gitlab.binghe.com時(shí),需要配置本機(jī)的hosts文件,在本機(jī)的hosts文件中加入如下配置項(xiàng)。
192.168.0.10 gitlab.binghe.com
注意:在Windows操作系統(tǒng)中,hosts文件所在的目錄如下。
C:\Windows\System32\drivers\etc
接下來,就可以在瀏覽器中通過鏈接:http://gitlab.binghe.com:30088 來訪問GitLab了,如下所示。
此時(shí),可以通過用戶名root和密碼admin.1231來登錄GitLab了。
注意:這里的用戶名是root而不是admin,因?yàn)閞oot是GitLab默認(rèn)的超級用戶。
到此,K8S安裝gitlab完成。
安裝Harbor私有倉庫
Habor是由VMWare公司開源的容器鏡像倉庫。事實(shí)上,Habor是在Docker Registry上進(jìn)行了相應(yīng)的企業(yè)級擴(kuò)展,從而獲得了更加廣泛的應(yīng)用,這些新的企業(yè)級特性包括:管理用戶界面,基于角色的訪問控制 ,AD/LDAP集成以及審計(jì)日志等,足以滿足基本企業(yè)需求。
注意:這里將Harbor私有倉庫安裝在Master節(jié)點(diǎn)(test10服務(wù)器)上,實(shí)際生產(chǎn)環(huán)境中建議安裝在其他服務(wù)器。
1.下載Harbor的離線安裝版本
wget https://github.com/goharbor/harbor/releases/download/v1.10.2/harbor-offline-installer-v1.10.2.tgz
2.解壓Harbor的安裝包
tar -zxvf harbor-offline-installer-v1.10.2.tgz
解壓成功后,會在服務(wù)器當(dāng)前目錄生成一個(gè)harbor目錄。
3.配置Harbor
注意:這里,我將Harbor的端口修改成了1180,如果不修改Harbor的端口,默認(rèn)的端口是80。
(1)修改harbor.yml文件
cd harbor vim harbor.yml
修改的配置項(xiàng)如下所示。
hostname: 192.168.0.10 http: port: 1180 harbor_admin_password: binghe123 ###并把https注釋掉,不然在安裝的時(shí)候會報(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文件,沒有的話就創(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.安裝并啟動harbor
配置完成后,輸入如下命令即可安裝并啟動Harbor
[root@binghe harbor]# ./install.sh
5.登錄Harbor并添加賬戶
安裝成功后,在瀏覽器地址欄輸入http://192.168.0.10:1180打開鏈接,輸入用戶名admin和密碼binghe123,登錄系統(tǒng)。
接下來,我們選擇用戶管理,添加一個(gè)管理員賬戶,為后續(xù)打包Docker鏡像和上傳Docker鏡像做準(zhǔn)備。
密碼為Binghe123。點(diǎn)擊確,此時(shí),賬戶binghe還不是管理員,此時(shí)選中binghe賬戶,點(diǎn)擊“設(shè)置為管理員”。
此時(shí),binghe賬戶就被設(shè)置為管理員了。到此,Harbor的安裝就完成了。
6.修改Harbor端口
如果安裝Harbor后,大家需要修改Harbor的端口,可以按照如下步驟修改Harbor的端口,這里,我以將80端口修改為1180端口為例
(1)修改harbor.yml文件
cd harbor vim harbor.yml
修改的配置項(xiàng)如下所示。
hostname: 192.168.0.10 http: port: 1180 harbor_admin_password: binghe123 ###并把https注釋掉,不然在安裝的時(shí)候會報(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/registry vim config.yml
修改的配置項(xiàng)如下所示。
realm: http://192.168.0.10:1180/service/token
(4)重啟Docker
systemctl daemon-reload systemctl restart docker.service
(5)重啟Harbor
[root@binghe harbor]# docker-compose down Stopping harbor-log ... done Removing nginx ... done Removing harbor-portal ... done Removing harbor-jobservice ... done Removing harbor-core ... done Removing redis ... done Removing registry ... done Removing registryctl ... done Removing harbor-db ... done Removing harbor-log ... done Removing network harbor_harbor [root@binghe harbor]# ./prepare prepare base dir is set to /mnt/harbor Clearing the configuration file: /config/log/logrotate.conf Clearing the configuration file: /config/nginx/nginx.conf Clearing the configuration file: /config/core/env Clearing the configuration file: /config/core/app.conf Clearing the configuration file: /config/registry/root.crt Clearing the configuration file: /config/registry/config.yml Clearing the configuration file: /config/registryctl/env Clearing the configuration file: /config/registryctl/config.yml Clearing the configuration file: /config/db/env Clearing the configuration file: /config/jobservice/env Clearing the configuration file: /config/jobservice/config.yml Generated configuration file: /config/log/logrotate.conf Generated configuration file: /config/nginx/nginx.conf Generated configuration file: /config/core/env Generated configuration file: /config/core/app.conf Generated configuration file: /config/registry/config.yml Generated configuration file: /config/registryctl/env Generated configuration file: /config/db/env Generated configuration file: /config/jobservice/env Generated configuration file: /config/jobservice/config.yml loaded secret from file: /secret/keys/secretkey Generated configuration file: /compose_location/docker-compose.yml Clean up the input dir [root@binghe harbor]# docker-compose up -d Creating network "harbor_harbor" with the default driver Creating harbor-log ... done Creating harbor-db ... done Creating redis ... done Creating registry ... done Creating registryctl ... done Creating harbor-core ... done Creating harbor-jobservice ... done Creating harbor-portal ... done Creating nginx ... done [root@binghe harbor]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
安裝Jenkins(一般的做法)
Jenkins是一個(gè)開源的、提供友好操作界面的持續(xù)集成(CI)工具,起源于Hudson(Hudson是商用的),主要用于持續(xù)、自動的構(gòu)建/測試軟件項(xiàng)目、監(jiān)控外部任務(wù)的運(yùn)行(這個(gè)比較抽象,暫且寫上,不做解釋)。Jenkins用Java語言編寫,可在Tomcat等流行的servlet容器中運(yùn)行,也可獨(dú)立運(yùn)行。通常與版本管理工具(SCM)、構(gòu)建工具結(jié)合使用。常用的版本控制工具有SVN、GIT,構(gòu)建工具有Maven、Ant、Gradle。
1.安裝nfs(之前安裝過的話,可以省略此步)
使用 nfs 最大的問題就是寫權(quán)限,可以使用 kubernetes 的 securityContext/runAsUser 指定 jenkins 容器中運(yùn)行 jenkins 的用戶 uid,以此來指定 nfs 目錄的權(quán)限,讓 jenkins 容器可寫;也可以不限制,讓所有用戶都可以寫。這里為了簡單,就讓所有用戶可寫了。
如果之前已經(jīng)安裝過nfs,則這一步可以省略。找一臺主機(jī),安裝 nfs,這里,我以在Master節(jié)點(diǎn)(test10服務(wù)器)上安裝nfs為例。
在命令行輸入如下命令安裝并啟動nfs。
yum install nfs-utils -y systemctl start nfs-server systemctl enable nfs-server
2.創(chuàng)建nfs共享目錄
在Master節(jié)點(diǎn)(test10服務(wù)器)上創(chuàng)建 /opt/nfs/jenkins-data目錄作為nfs的共享目錄,如下所示。
mkdir -p /opt/nfs/jenkins-data
接下來,編輯/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)會將所有訪問的用戶都映射成 nfsnobody 用戶,不管你是什么用戶訪問,最終都會壓縮成 nfsnobody,所以只要將 /opt/nfs/jenkins-data 的屬主改為 nfsnobody,那么無論什么用戶來訪問都具有寫權(quán)限。
這個(gè)選項(xiàng)在很多機(jī)器上由于用戶 uid 不規(guī)范導(dǎo)致啟動進(jìn)程的用戶不同,但是同時(shí)要對一個(gè)共享目錄具有寫權(quán)限時(shí)很有效。
接下來,為 /opt/nfs/jenkins-data目錄授權(quán),并重新加載nfs,如下所示。
#為/opt/nfs/jenkins-data/目錄授權(quán) chown -R 1000 /opt/nfs/jenkins-data/ #重新加載nfs-server systemctl 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.10 Export list for 192.168.0.10: /opt/nfs/jenkins-data 192.168.175.0/24 [root@test11 ~]# showmount -e 192.168.0.10 Export list for 192.168.0.10: /opt/nfs/jenkins-data 192.168.175.0/24
3.創(chuàng)建PV
Jenkins 其實(shí)只要加載對應(yīng)的目錄就可以讀取之前的數(shù)據(jù),但是由于 deployment 無法定義存儲卷,因此我們只能使用 StatefulSet。
首先創(chuàng)建 pv,pv 是給 StatefulSet 使用的,每次 StatefulSet 啟動都會通過 volumeClaimTemplates 這個(gè)模板去創(chuàng)建 pvc,因此必須得有 pv,才能供 pvc 綁定。
創(chuàng)建jenkins-pv.yaml文件,文件內(nèi)容如下所示。
apiVersion: v1
kind: PersistentVolume
metadata:
name: jenkins
spec:
nfs:
path: /opt/nfs/jenkins-data
server: 192.168.0.10
accessModes: ["ReadWriteOnce"]
capacity:
storage: 1Ti
我這里給了 1T存儲空間,可以根據(jù)實(shí)際配置。
執(zhí)行如下命令創(chuàng)建pv。
kubectl apply -f jenkins-pv.yaml
4.創(chuàng)建serviceAccount
創(chuàng)建service account,因?yàn)?jenkins 后面需要能夠動態(tài)創(chuàng)建 slave,因此它必須具備一些權(quán)限。
創(chuàng)建jenkins-service-account.yaml文件,文件內(nèi)容如下所示。
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: jenkins
rules:
- 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/v1beta1
kind: RoleBinding
metadata:
name: jenkins
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: jenkins
subjects:
- kind: ServiceAccount
name: jenkins
上述配置中,創(chuàng)建了一個(gè) RoleBinding 和一個(gè) ServiceAccount,并且將 RoleBinding 的權(quán)限綁定到這個(gè)用戶上。所以,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 證書。
執(zhí)行如下命令創(chuàng)建serviceAccount。
kubectl apply -f jenkins-service-account.yaml
5.安裝Jenkins
創(chuàng)建jenkins-statefulset.yaml文件,文件內(nèi)容如下所示。
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: jenkins
labels:
name: jenkins
spec:
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 模板,對應(yīng)之前的 pv
volumeClaimTemplates:
- metadata:
name: jenkins-home
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Ti
jenkins 部署時(shí)需要注意它的副本數(shù),你的副本數(shù)有多
版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非maisonbaluchon.cn所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。
關(guān)注官方微信