【K8S】基於Docker+K8S+GitLab/SVN+Jenkins+Harbor搭建持續集成交付環境(環境搭建篇)

環境搭建概述

1.K8S是什麼?

K8S全稱是Kubernetes,是一個全新的基於容器技術的分佈式架構領先方案,基於容器技術,目的是實現資源管理的自動化,以及跨多個數據中心的資源利用率的最大化。java

若是咱們的系統設計遵循了kubernetes的設計思想,那麼傳統系統架構中那些和業務沒有多大關係的底層代碼或功能模塊,均可以使用K8S來管理,咱們沒必要再費心於負載均衡的選型和部署實施問題,沒必要再考慮引入或本身開發一個複雜的服務治理框架,沒必要再頭疼與服務監控和故障處理模塊的開發。總之,使用kubernetes提供的解決方案,會大大減小開發成本,同時能夠將精力更加集中於業務自己,並且因爲kubernetes提供了強大的自動化機制,因此係統後期的運維難度和運維成本大幅下降。node

2.爲何要用K8S?

Docker 這個新興的容器化技術當前已經被不少公司所採用,其從單機走向集羣已成必然,而云計算的蓬勃發展正在加速這一進程。Kubernetes 做爲當前惟一被業界普遍承認和看好的 Docker 分佈式系統解決方案。能夠預見,在將來幾年內,會有大量的新系統選擇它,無論是運行在企業本地服務器上仍是被託管到公有云上。linux

3.使用K8S有哪些好處?

使用Kubernetes就是在全面部署微服務架構。微服務架構的核心就是將一個巨大的單體應用分解爲不少小的互相鏈接的微服務,一個微服務背後可能有多個實例副本在支撐,副本的數量可能會隨着系統的負荷變化而進行調整,內嵌的負載均衡器在 k8s 平臺中有多個實例副本在支撐,副本的數量可能會隨着系統的負荷變化而進行調整,內嵌的負載均衡器 在k8s 平臺中發揮了重要的做用。微服務架構使得每一個服務均可以由專門的開發團隊來開發,開發者能夠自由選擇開發技術,這對於大規模團隊來講頗有價值。另外,每一個微服務獨立開發、升級、擴展,使得系統具有很高的穩定性和快速迭代進化能力。nginx

4.環境構成

整套環境的搭建包含:Docker環境的搭建、docker-compose環境的搭建、K8S集羣的搭建、GitLab代碼倉庫的搭建、SVN倉庫的搭建、Jenkins自動化部署環境的搭建、Harbor私有倉庫的搭建。git

本文檔中,整套環境的搭建包括:github

  • 安裝Docker環境
  • 安裝docker-compose
  • 安裝K8S集羣環境
  • 重啓K8S集羣引發的問題
  • K8S安裝ingress-nginx
  • K8S安裝gitlab代碼倉庫
  • 安裝Harbor私有倉庫
  • 安裝Jenkins
  • 物理機安裝SVN(推薦)
  • 物理機安裝Jenkins(推薦)
  • 配置Jenkins運行環境
  • Jenkins發佈Docker項目到K8S

服務器規劃

IP 主機名 節點 操做系統
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

安裝環境版本

軟件名稱 軟件版本 說明
Docker 19.03.8 提供容器環境
docker-compose 1.25.5 定義和運行由多個容器組成的應用
K8S 1.18.2 是一個開源的,用於管理雲平臺中多個主機上的容器化的應用,Kubernetes的目標是讓部署容器化的應用簡單而且高效(powerful),Kubernetes提供了應用部署,規劃,更新,維護的一種機制。
GitLab 12.1.6 代碼倉庫
Harbor 1.10.2 私有鏡像倉庫
Jenkins 2.222.3 持續集成交付

安裝Docker環境

Docker 是一個開源的應用容器引擎,基於 Go 語言 並聽從 Apache2.0 協議開源。web

Docker 可讓開發者打包他們的應用以及依賴包到一個輕量級、可移植的容器中,而後發佈到任何流行的 Linux 機器上,也能夠實現虛擬化。redis

本文檔基於Docker 19.03.8 版本搭建Docker環境。spring

在全部服務器上建立install_docker.sh腳本,腳本內容以下所示。sql

#使用阿里雲鏡像中心
export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com
#安裝yum工具
dnf install yum*
#安裝docker環境
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
#設置Docker開機啓動
systemctl enable docker.service
#啓動Docker
systemctl start docker.service
#查看Docker版本
docker version

在每臺服務器上爲install_docker.sh腳本賦予可執行權限,並執行腳本,以下所示。

# 賦予install_docker.sh腳本可執行權限
chmod a+x ./install_docker.sh
# 執行install_docker.sh腳本
./install_docker.sh

安裝docker-compose

Compose 是用於定義和運行多容器 Docker 應用程序的工具。經過 Compose,您可使用 YML 文件來配置應用程序須要的全部服務。而後,使用一個命令,就能夠從 YML 文件配置中建立並啓動全部服務。

注意:在每臺服務器上安裝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文件賦予可執行權限

#賦予docker-compose可執行權限
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集羣環境

Kubernetes是一個開源的,用於管理雲平臺中多個主機上的容器化的應用,Kubernetes的目標是讓部署容器化的應用簡單而且高效(powerful),Kubernetes提供了應用部署,規劃,更新,維護的一種機制。

本文檔基於K8S 1.8.12版原本搭建K8S集羣

安裝K8S基礎環境

在全部服務器上建立install_k8s.sh腳本文件,腳本文件的內容以下所示。

#################配置阿里雲鏡像加速器開始########################
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://zz3sblpi.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker
######################配置阿里雲鏡像加速器結束#########################
#安裝nfs-utils
yum install -y nfs-utils
#安裝wget軟件下載命令
yum install -y wget

#啓動nfs-server
systemctl start nfs-server
#配置nfs-server開機自啓動
systemctl enable nfs-server

#關閉防火牆
systemctl stop firewalld
#取消防火牆開機自啓動
systemctl disable firewalld

#關閉SeLinux
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config

# 關閉 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結束###########################
# 執行命令使修改後的/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源結束#############################

# 卸載舊版本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 節點時可能會碰到以下錯誤
# [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

# 設置 docker 鏡像,提升 docker 鏡像下載速度和穩定性
# 若是訪問 https://hub.docker.io 速度很是穩定,也能夠跳過這個步驟,通常不需配置
# curl -sSL https://kuboard.cn/install-script/set_mirror.sh | sh -s ${REGISTRY_MIRROR}

# 從新加載配置文件
systemctl daemon-reload
#重啓 docker
systemctl restart docker
# 將kubelet設置爲開機啓動並啓動kubelet
systemctl enable kubelet && systemctl start kubelet
# 查看docker版本
docker version

在每臺服務器上爲install_k8s.sh腳本賦予可執行權限,並執行腳本

# 賦予install_k8s.sh腳本可執行權限
chmod a+x ./install_k8s.sh
# 運行install_k8s.sh腳本
./install_k8s.sh

初始化Master節點

只在test10服務器上執行的操做。

1.初始化Master節點的網絡環境

注意:下面的命令須要在命令行手動執行。

# 只在 master 節點執行
# export 命令只在當前 shell 會話中有效,開啓新的 shell 窗口後,若是要繼續安裝過程,請從新執行此處的 export 命令
export MASTER_IP=192.168.0.10
# 替換 k8s.master 爲 您想要的 dnsName
export APISERVER_NAME=k8s.master
# Kubernetes 容器組所在的網段,該網段安裝完成後,由 kubernetes 建立,事先並不存在於物理網絡中
export POD_SUBNET=172.18.0.1/16
echo "${MASTER_IP}    ${APISERVER_NAME}" >> /etc/hosts

2.初始化Master節點

在test10服務器上建立init_master.sh腳本文件,文件內容以下所示。

#!/bin/bash
# 腳本出錯時終止執行
set -e

if [ ${#POD_SUBNET} -eq 0 ] || [ ${#APISERVER_NAME} -eq 0 ]; then
  echo -e "\033[31;1m請確保您已經設置了環境變量 POD_SUBNET 和 APISERVER_NAME \033[0m"
  echo 當前POD_SUBNET=$POD_SUBNET
  echo 當前APISERVER_NAME=$APISERVER_NAME
  exit 1
fi


# 查看完整配置選項 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 網絡插件
# 參考文檔 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腳本文件可執行權限並執行腳本。

# 賦予init_master.sh文件可執行權限
chmod a+x ./init_master.sh
# 運行init_master.sh腳本
./init_master.sh

3.查看Master節點的初始化結果

(1)確保全部容器組處於Running狀態

# 執行以下命令,等待 3-10 分鐘,直到全部的容器組處於 Running 狀態
watch kubectl get pod -n kube-system -o wide

具體執行以下所示。

[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>           <none>

(2) 查看 Master 節點初始化結果

# 查看Master節點的初始化結果
kubectl get nodes -o wide

具體執行以下所示。

[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節點

1.獲取join命令參數

在Master節點(test10服務器)上執行以下命令獲取join命令參數。

kubeadm token create --print-join-command

具體執行以下所示。

[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的有效時間爲 2 個小時,2小時內,可使用此 token 初始化任意數量的 worker 節點。

2.初始化Worker節點

針對全部的 worker 節點執行,在這裏,就是在test11服務器和test12服務器上執行。

在命令分別手動執行以下命令。

# 只在 worker 節點執行
# 192.168.0.10 爲 master 節點的內網 IP
export MASTER_IP=192.168.0.10
# 替換 k8s.master 爲初始化 master 節點時所使用的 APISERVER_NAME
export APISERVER_NAME=k8s.master
echo "${MASTER_IP}    ${APISERVER_NAME}" >> /etc/hosts

# 替換爲 master 節點上 kubeadm token create 命令輸出的join
kubeadm join k8s.master:6443 --token 8nblts.62xytoqufwsqzko2     --discovery-token-ca-cert-hash sha256:1717cc3e34f6a56b642b5751796530e367aa73f4113d09994ac3455e33047c0d

具體執行以下所示。

[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.

根據輸出結果能夠看出,Worker節點加入了K8S集羣。

注意:kubeadm join…就是master 節點上 kubeadm token create 命令輸出的join。

3.查看初始化結果

在Master節點(test10服務器)執行以下命令查看初始化結果。

kubectl get nodes -o wide

具體執行以下所示。

[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參數能夠輸出更多的信息。

重啓K8S集羣引發的問題

1.Worker節點故障不能啓動

Master 節點的 IP 地址發生變化,致使 worker 節點不能啓動。須要從新安裝K8S集羣,並確保全部節點都有固定的內網 IP 地址。

2.Pod崩潰或不能正常訪問

重啓服務器後使用以下命令查看Pod的運行狀態。

#查看全部pod的運行狀況
kubectl get pods --all-namespaces

發現不少 Pod 不在 Running 狀態,此時,須要使用以下命令刪除運行不正常的Pod。

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

注意:若是Pod 是使用 Deployment、StatefulSet 等控制器建立的,K8S 將建立新的 Pod 做爲替代,從新啓動的 Pod 一般可以正常工做。

其中,pod-name表示運行在K8S中的pod的名稱,pod-namespece表示命名空間。例如,須要刪除pod名稱爲pod-test,命名空間爲pod-test-namespace的pod,可使用下面的命令。

kubectl delete pod pod-test -n pod-test-namespace

K8S安裝ingress-nginx

做爲反向代理將外部流量導入集羣內部,將 Kubernetes 內部的 Service 暴露給外部,在 Ingress 對象中經過域名匹配 Service,這樣就能夠直接經過域名訪問到集羣內部的服務了。相對於 traefik 來講,nginx-ingress 性能更加優秀。

注意:在Master節點(test10服務器上執行)

1.建立ingress-nginx命名空間

建立ingress-nginx-namespace.yaml文件,主要的做用是建立ingress-nginx命名空間,文件內容以下所示。

apiVersion: v1
kind: Namespace
metadata:
  name: ingress-nginx
  labels:
    name: ingress-nginx

執行以下命令建立ingress-nginx命名空間。

kubectl apply -f ingress-nginx-namespace.yaml

2.安裝ingress controller

建立ingress-nginx-mandatory.yaml文件,主要的做用是安裝ingress-nginx。文件內容以下所示。

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

---

執行以下命令安裝ingress controller。

kubectl apply -f ingress-nginx-mandatory.yaml

3.安裝K8S SVC:ingress-nginx

主要是用來用於暴露pod:nginx-ingress-controller。

建立service-nodeport.yaml文件,文件內容以下所示。

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

執行以下命令安裝。

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

在命令行服務器命令行輸入以下命令查看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節點(test10服務器)的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.開發,使用MIT許可證的基於網絡的Git倉庫管理工具,且具備Wiki和issue跟蹤功能。使用Git做爲代碼管理工具,並在此基礎上搭建起來的web服務。

注意:在Master節點(test10服務器上執行)

1.建立k8s-ops命名空間

建立k8s-ops-namespace.yaml文件,主要做用是建立k8s-ops命名空間。文件內容以下所示。

apiVersion: v1
kind: Namespace
metadata:
  name: k8s-ops
  labels:
    name: k8s-ops

執行以下命令建立命名空間。

kubectl apply -f k8s-ops-namespace.yaml

2.安裝gitlab-redis

建立gitlab-redis.yaml文件,文件的內容以下所示。

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

首先,在命令行執行以下命令建立/data1/docker/xinsrv/redis目錄。

mkdir -p /data1/docker/xinsrv/redis

執行以下命令安裝gitlab-redis。

kubectl apply -f gitlab-redis.yaml

3.安裝gitlab-postgresql

建立gitlab-postgresql.yaml,文件內容以下所示。

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

首先,執行以下命令建立/data1/docker/xinsrv/postgresql目錄。

mkdir -p /data1/docker/xinsrv/postgresql

接下來,安裝gitlab-postgresql,以下所示。

kubectl apply -f gitlab-postgresql.yaml

4.安裝gitlab

(1)配置用戶名和密碼

首先,在命令行使用base64編碼爲用戶名和密碼進行轉碼,本示例中,使用的用戶名爲admin,密碼爲admin.1231

轉碼狀況以下所示。

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

轉碼後的用戶名爲:YWRtaW4= 密碼爲:YWRtaW4uMTIzMQ==

也能夠對base64編碼後的字符串解碼,例如,對密碼字符串解碼,以下所示。

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

接下來,建立secret-gitlab.yaml文件,主要是用戶來配置GitLab的用戶名和密碼,文件內容以下所示。

apiVersion: v1
kind: Secret
metadata:
  namespace: k8s-ops
  name: git-user-pass
type: Opaque
data:
  username: YWRtaW4=
  password: YWRtaW4uMTIzMQ==

執行配置文件的內容,以下所示。

kubectl create -f ./secret-gitlab.yaml

(2)安裝GitLab

建立gitlab.yaml文件,文件的內容以下所示。

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時,監聽主機時,不能使用IP地址,須要使用主機名或者域名,上述配置中,我使用的是gitlab.binghe.com主機名。

在命令行執行以下命令建立/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

此時,能夠看到,能夠經過Master節點(test10)的主機名gitlab.binghe.com和端口30088就可以訪問GitLab。因爲我這裏使用的是虛擬機來搭建相關的環境,在本機訪問虛擬機映射的gitlab.binghe.com時,須要配置本機的hosts文件,在本機的hosts文件中加入以下配置項。

192.168.0.10 gitlab.binghe.com

注意:在Windows操做系統中,hosts文件所在的目錄以下。

C:\Windows\System32\drivers\etc

接下來,就能夠在瀏覽器中經過連接:http://gitlab.binghe.com:30088 來訪問GitLab了,以下所示。

此時,能夠經過用戶名root和密碼admin.1231來登陸GitLab了。

注意:這裏的用戶名是root而不是admin,由於root是GitLab默認的超級用戶。

到此,K8S安裝gitlab完成。

安裝Harbor私有倉庫

Habor是由VMWare公司開源的容器鏡像倉庫。事實上,Habor是在Docker Registry上進行了相應的企業級擴展,從而得到了更加普遍的應用,這些新的企業級特性包括:管理用戶界面,基於角色的訪問控制 ,AD/LDAP集成以及審計日誌等,足以知足基本企業需求。

注意:這裏將Harbor私有倉庫安裝在Master節點(test10服務器)上,實際生產環境中建議安裝在其餘服務器。

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

解壓成功後,會在服務器當前目錄生成一個harbor目錄。

3.配置Harbor

注意:這裏,我將Harbor的端口修改爲了1180,若是不修改Harbor的端口,默認的端口是80。

(1)修改harbor.yml文件

cd harbor
vim harbor.yml

修改的配置項以下所示。

hostname: 192.168.0.10
http:
  port: 1180
harbor_admin_password: binghe123
###並把https註釋掉,否則在安裝的時候會報錯: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文件,沒有的話就建立,在/etc/docker/daemon.json文件中添加以下內容。

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

也能夠在服務器上使用 ip addr 命令查看本機全部的IP地址段,將其配置到/etc/docker/daemon.json文件中。這裏,我配置後的文件內容以下所示。

{
    "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,登陸系統。

接下來,咱們選擇用戶管理,添加一個管理員帳戶,爲後續打包Docker鏡像和上傳Docker鏡像作準備。

密碼爲Binghe123。點擊確,此時,帳戶binghe還不是管理員,此時選中binghe帳戶,點擊「設置爲管理員」。

此時,binghe帳戶就被設置爲管理員了。到此,Harbor的安裝就完成了。

6.修改Harbor端口

若是安裝Harbor後,你們須要修改Harbor的端口,能夠按照以下步驟修改Harbor的端口,這裏,我以將80端口修改成1180端口爲例

(1)修改harbor.yml文件

cd harbor
vim harbor.yml

修改的配置項以下所示。

hostname: 192.168.0.10
http:
  port: 1180
harbor_admin_password: binghe123
###並把https註釋掉,否則在安裝的時候會報錯: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

修改的配置項以下所示。

ports:
      - 1180:80

(3)修改config.yml文件

cd common/config/registry
vim config.yml

修改的配置項以下所示。

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是一個開源的、提供友好操做界面的持續集成(CI)工具,起源於Hudson(Hudson是商用的),主要用於持續、自動的構建/測試軟件項目、監控外部任務的運行(這個比較抽象,暫且寫上,不作解釋)。Jenkins用Java語言編寫,可在Tomcat等流行的servlet容器中運行,也可獨立運行。一般與版本管理工具(SCM)、構建工具結合使用。經常使用的版本控制工具備SVN、GIT,構建工具備Maven、Ant、Gradle。

1.安裝nfs(以前安裝過的話,能夠省略此步)

使用 nfs 最大的問題就是寫權限,可使用 kubernetes 的 securityContext/runAsUser 指定 jenkins 容器中運行 jenkins 的用戶 uid,以此來指定 nfs 目錄的權限,讓 jenkins 容器可寫;也能夠不限制,讓全部用戶均可以寫。這裏爲了簡單,就讓全部用戶可寫了。

若是以前已經安裝過nfs,則這一步能夠省略。找一臺主機,安裝 nfs,這裏,我以在Master節點(test10服務器)上安裝nfs爲例。

在命令行輸入以下命令安裝並啓動nfs。

yum install nfs-utils -y
systemctl start nfs-server
systemctl enable nfs-server

2.建立nfs共享目錄

在Master節點(test10服務器)上建立 /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 節點的 ip 範圍,後面的 all_squash 選項會將全部訪問的用戶都映射成 nfsnobody 用戶,無論你是什麼用戶訪問,最終都會壓縮成 nfsnobody,因此只要將 /opt/nfs/jenkins-data 的屬主改成 nfsnobody,那麼不管什麼用戶來訪問都具備寫權限。

這個選項在不少機器上因爲用戶 uid 不規範致使啓動進程的用戶不一樣,可是同時要對一個共享目錄具備寫權限時頗有效。

接下來,爲 /opt/nfs/jenkins-data目錄受權,並從新加載nfs,以下所示。

#爲/opt/nfs/jenkins-data/目錄受權
chown -R 1000 /opt/nfs/jenkins-data/
#從新加載nfs-server
systemctl reload nfs-server

在K8S集羣中任意一個節點上使用以下命令進行驗證:

#查看nfs系統的目錄權限
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.建立PV

Jenkins 其實只要加載對應的目錄就能夠讀取以前的數據,可是因爲 deployment 沒法定義存儲卷,所以咱們只能使用 StatefulSet。

首先建立 pv,pv 是給 StatefulSet 使用的,每次 StatefulSet 啓動都會經過 volumeClaimTemplates 這個模板去建立 pvc,所以必須得有 pv,才能供 pvc 綁定。

建立jenkins-pv.yaml文件,文件內容以下所示。

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存儲空間,能夠根據實際配置。

執行以下命令建立pv。

kubectl apply -f jenkins-pv.yaml

4.建立serviceAccount

建立service account,由於 jenkins 後面須要可以動態建立 slave,所以它必須具有一些權限。

建立jenkins-service-account.yaml文件,文件內容以下所示。

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

上述配置中,建立了一個 RoleBinding 和一個 ServiceAccount,而且將 RoleBinding 的權限綁定到這個用戶上。因此,jenkins 容器必須使用這個 ServiceAccount 運行才行,否則 RoleBinding 的權限它將不具有。

RoleBinding 的權限很容易就看懂了,由於 jenkins 須要建立和刪除 slave,因此才須要上面這些權限。至於 secrets 權限,則是 https 證書。

執行以下命令建立serviceAccount。

kubectl apply -f jenkins-service-account.yaml

5.安裝Jenkins

建立jenkins-statefulset.yaml文件,文件內容以下所示。

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 模板,對應以前的 pv
  volumeClaimTemplates:
    - metadata:
        name: jenkins-home
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 1Ti

jenkins 部署時須要注意它的副本數,你的副本數有多少就要有多少個 pv,一樣,存儲會有多倍消耗。這裏我只使用了一個副本,所以前面也只建立了一個 pv。

使用以下命令安裝Jenkins。

kubectl apply -f jenkins-statefulset.yaml

6.建立Service

建立jenkins-service.yaml文件,主要用於後臺運行Jenkins,文件內容以下所示。

apiVersion: v1
kind: Service
metadata:
  name: jenkins
spec:
  # 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 界面須要從集羣外訪問,這裏咱們選擇的是使用 ingress。建立jenkins-ingress.yaml文件,文件內容以下所示。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: jenkins
spec:
  rules:
    - http:
        paths:
          - path: /
            backend:
              serviceName: jenkins
              servicePort: 31888
      host: jekins.binghe.com

這裏,須要注意的是host必須配置爲域名或者主機名,不然會報錯,以下所示。

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

最後,因爲我這裏使用的是虛擬機來搭建相關的環境,在本機訪問虛擬機映射的jekins.binghe.com時,須要配置本機的hosts文件,在本機的hosts文件中加入以下配置項。

192.168.0.10 jekins.binghe.com

注意:在Windows操做系統中,hosts文件所在的目錄以下。

C:\Windows\System32\drivers\etc

接下來,就能夠在瀏覽器中經過連接:http://jekins.binghe.com:31888 來訪問Jekins了。

物理機安裝SVN

Apache Subversion 一般被縮寫成 SVN,是一個開放源代碼的版本控制系統,Subversion 在 2000 年由 CollabNet Inc 開發,如今發展成爲 Apache 軟件基金會的一個項目,一樣是一個豐富的開發者和用戶社區的一部分。

SVN相對於的RCS、CVS,採用了分支管理系統,它的設計目標就是取代CVS。互聯網上免費的版本控制服務多基於Subversion。

這裏,以在Master節點(binghe101服務器)上安裝SVN爲例。

1.使用yum安裝SVN

在命令行執行以下命令安裝SVN。

yum -y install subversion

2.建立SVN庫

依次執行以下命令。

#建立/data/svn
mkdir -p /data/svn 
#初始化svn
svnserve -d -r /data/svn
#建立代碼倉庫
svnadmin create /data/svn/test

3.配置SVN

mkdir /data/svn/conf
cp /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

配置後的內容以下所示。

[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,&joe
SuperAdmin = admin
binghe = admin,binghe

# [/foo/bar]
# harry = rw
# &joe = r
# * =

# [repository:/baz/fuz]
# @harry_and_sally = rw
# * = r

[test:/]
@SuperAdmin=rw
@binghe=rw
  • 配置passwd文件
vim passwd

配置後的內容以下所示。

[users]
# harry = harryssecret
# sally = sallyssecret
admin = admin123
binghe = 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 = none
auth-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

接下來,將/data/svn/conf目錄下的svnserve.conf文件複製到/data/svn/test/conf/目錄下。以下所示。

[root@binghe101 conf]# cp /data/svn/conf/svnserve.conf /data/svn/test/conf/
cp:是否覆蓋'/data/svn/test/conf/svnserve.conf'? y

4.啓動SVN服務

(1)建立svnserve.service服務

建立svnserve.service文件

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

文件的內容以下所示。

[Unit]
Description=Subversion protocol daemon
After=syslog.target network.target
Documentation=man:svnserve(8)

[Service]
Type=forking
EnvironmentFile=/etc/sysconfig/svnserve
#ExecStart=/usr/bin/svnserve --daemon --pid-file=/run/svnserve/svnserve.pid $OPTIONS
ExecStart=/usr/bin/svnserve --daemon $OPTIONS
PrivateTmp=yes

[Install]
WantedBy=multi-user.target

接下來執行以下命令使配置生效。

systemctl daemon-reload

命令執行成功後,修改 /etc/sysconfig/svnserve 文件。

vim /etc/sysconfig/svnserve

修改後的文件內容以下所示。

# OPTIONS is used to pass command-line arguments to svnserve.
# 
# Specify the repository location in -r parameter:
OPTIONS="-r /data/svn"

(2)啓動SVN

首先查看SVN狀態,以下所示。

[root@test10 conf]# systemctl status svnserve.service
● svnserve.service - Subversion protocol daemon
   Loaded: loaded (/usr/lib/systemd/system/svnserve.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:svnserve(8)

能夠看到,此時SVN並無啓動,接下來,須要啓動SVN。

systemctl start svnserve.service

設置SVN服務開機自啓動。

systemctl enable svnserve.service

接下來,就能夠下載安裝TortoiseSVN,輸入連接svn://192.168.0.10/test 並輸入用戶名binghe,密碼binghe123來鏈接SVN了。

Docker安裝SVN

拉取SVN鏡像

docker pull docker.io/elleflorio/svn-server

啓動SVN容器

docker run -v /usr/local/svn:/home/svn -v /usr/local/svn/passwd:/etc/subversion/passwd -v /usr/local/apache2:/run/apache2 --name svn_server -p 3380:80 -p 3690:3960 -e SVN_REPONAME=repos -d docker.io/elleflorio/svn-server

進入SVN容器內部

docker exec -it svn_server bash

進入容器後,能夠參照物理機安裝SVN的方式配置SVN倉庫。

物理機安裝Jenkins

注意:安裝Jenkins以前須要安裝JDK和Maven,我這裏一樣將Jenkins安裝在Master節點(binghe101服務器)。

1.啓用Jenkins庫

運行如下命令如下載repo文件並導入GPG密鑰:

wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat-stable/jenkins.repo
rpm --import https://jenkins-ci.org/redhat/jenkins-ci.org.key

2.安裝Jenkins

執行以下命令安裝Jenkis。

yum install jenkins

接下來,修改Jenkins默認端口,以下所示。

vim /etc/sysconfig/jenkins

修改後的兩項配置以下所示。

JENKINS_JAVA_CMD="/usr/local/jdk1.8.0_212/bin/java"
JENKINS_PORT="18080"

此時,已經將Jenkins的端口由8080修改成18080

3.啓動Jenkins

在命令行輸入以下命令啓動Jenkins。

systemctl start jenkins

配置Jenkins開機自啓動。

systemctl enable jenkins

查看Jenkins的運行狀態。

[root@test10 ~]# systemctl status jenkins
● jenkins.service - LSB: Jenkins Automation Server
   Loaded: loaded (/etc/rc.d/init.d/jenkins; generated)
   Active: active (running) since Tue 2020-05-12 04:33:40 EDT; 28s ago
     Docs: man:systemd-sysv-generator(8)
    Tasks: 71 (limit: 26213)
   Memory: 550.8M

說明,Jenkins啓動成功。

配置Jenkins運行環境

1.登陸Jenkins

首次安裝後,須要配置Jenkins的運行環境。首先,在瀏覽器地址欄訪問連接http://192.168.0.10:18080,打開Jenkins界面。

根據提示使用以下命令到服務器上找密碼值,以下所示。

[root@binghe101 ~]# cat /var/lib/jenkins/secrets/initialAdminPassword
71af861c2ab948a1b6efc9f7dde90776

將密碼71af861c2ab948a1b6efc9f7dde90776複製到文本框,點擊繼續。會跳轉到自定義Jenkins頁面,以下所示。

這裏,能夠直接選擇「安裝推薦的插件」。以後會跳轉到一個安裝插件的頁面,以下所示。

此步驟可能有下載失敗的狀況,可直接忽略。

2.安裝插件

須要安裝的插件

  • Kubernetes Cli Plugin:該插件可直接在Jenkins中使用kubernetes命令行進行操做。
  • Kubernetes plugin: 使用kubernetes則須要安裝該插件
  • Kubernetes Continuous Deploy Plugin:kubernetes部署插件,可根據須要使用

還有更多的插件可供選擇,可點擊 系統管理->管理插件進行管理和添加,安裝相應的Docker插件、SSH插件、Maven插件。其餘的插件能夠根據須要進行安裝。以下圖所示。

3.配置Jenkins

(1)配置JDK和Maven

在Global Tool Configuration中配置JDK和Maven,以下所示,打開Global Tool Configuration界面。

接下來就開始配置JDK和Maven了。

因爲我在服務器上將Maven安裝在/usr/local/maven-3.6.3目錄下,因此,須要在「Maven 配置」中進行配置,以下圖所示。

接下來,配置JDK,以下所示。

注意:不要勾選「Install automatically」

接下來,配置Maven,以下所示。

注意:不要勾選「Install automatically」

(2)配置SSH

進入Jenkins的Configure System界面配置SSH,以下所示。

找到 SSH remote hosts 進行配置。

配置完成後,點擊Check connection按鈕,會顯示 Successfull connection。以下所示。

至此,Jenkins的基本配置就完成了。

Jenkins發佈Docker項目到K8s集羣

1.調整SpringBoot項目的配置

實現,SpringBoot項目中啓動類所在的模塊的pom.xml須要引入打包成Docker鏡像的配置,以下所示。

<properties>
  	 	<docker.repostory>192.168.0.10:1180</docker.repostory>
        <docker.registry.name>test</docker.registry.name>
        <docker.image.tag>1.0.0</docker.image.tag>
        <docker.maven.plugin.version>1.4.10</docker.maven.plugin.version>
  </properties>

<build>
  		<finalName>test-starter</finalName>
		<plugins>
            <plugin>
			    <groupId>org.springframework.boot</groupId>
			    <artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			
			<!-- docker的maven插件,官網:https://github.com/spotify/docker‐maven‐plugin -->
			<!-- Dockerfile maven plugin -->
			<plugin>
			    <groupId>com.spotify</groupId>
			    <artifactId>dockerfile-maven-plugin</artifactId>
			    <version>${docker.maven.plugin.version}</version>
			    <executions>
			        <execution>
			        <id>default</id>
			        <goals>
			            <!--若是package時不想用docker打包,就註釋掉這個goal-->
			            <goal>build</goal>
			            <goal>push</goal>
			        </goals>
			        </execution>
			    </executions>
			    <configuration>
			    	<contextDirectory>${project.basedir}</contextDirectory>
			        <!-- harbor 倉庫用戶名及密碼-->
			        <useMavenSettingsForAuth>useMavenSettingsForAuth>true</useMavenSettingsForAuth>
			        <repository>${docker.repostory}/${docker.registry.name}/${project.artifactId}</repository>
			        <tag>${docker.image.tag}</tag>
			        <buildArgs>
			            <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
			        </buildArgs>
			    </configuration>
			</plugin>

        </plugins>
        
		<resources>
			<!-- 指定 src/main/resources下全部文件及文件夾爲資源文件 -->
			<resource>
				<directory>src/main/resources</directory>
				<targetPath>${project.build.directory}/classes</targetPath>
				<includes>
					<include>**/*</include>
				</includes>
				<filtering>true</filtering>
			</resource>
		</resources>
	</build>

接下來,在SpringBoot啓動類所在模塊的根目錄建立Dockerfile,內容示例以下所示。

#添加依賴環境,前提是將Java8的Docker鏡像從官方鏡像倉庫pull下來,而後上傳到本身的Harbor私有倉庫中
FROM 192.168.0.10:1180/library/java:8
#指定鏡像製做做者
MAINTAINER binghe
#運行目錄
VOLUME /tmp
#將本地的文件拷貝到容器
ADD target/*jar app.jar
#啓動容器後自動執行的命令
ENTRYPOINT [ "java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar" ]

根據實際狀況,自行修改。

注意:FROM 192.168.0.10:1180/library/java:8的前提是執行以下命令。

docker pull java:8
docker tag java:8 192.168.0.10:1180/library/java:8
docker login 192.168.0.10:1180
docker push 192.168.0.10:1180/library/java:8

在SpringBoot啓動類所在模塊的根目錄建立yaml文件,錄入叫作test.yaml文件,內容以下所示。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-starter
  labels:
    app: test-starter
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-starter
  template:
    metadata:
      labels:
        app: test-starter
    spec:
      containers:
      - name: test-starter
        image: 192.168.0.10:1180/test/test-starter:1.0.0
        ports:
        - containerPort: 8088
      nodeSelector:
        clustertype: node12

---
apiVersion: v1
kind: Service
metadata:
  name: test-starter
  labels:
    app: test-starter
spec:
  ports:
    - name: http
      port: 8088
      nodePort: 30001
  type: NodePort
  selector:
    app: test-starter

2.Jenkins配置發佈項目

將項目上傳到SVN代碼庫,例如地址爲svn://192.168.0.10/test

接下來,在Jenkins中配置自動發佈。步驟以下所示。

點擊新建Item。

在描述文本框中輸入描述信息,以下所示。

接下來,配置SVN信息。

注意:配置GitLab的步驟與SVN相同,再也不贅述。

定位到Jenkins的「構建模塊」,使用Execute Shell來構建發佈項目到K8S集羣。

執行的命令依次以下所示。

#刪除本地原有的鏡像,不會影響Harbor倉庫中的鏡像
docker rmi 192.168.0.10:1180/test/test-starter:1.0.0
#使用Maven編譯、構建Docker鏡像,執行完成後本地Docker容器中會從新構建鏡像文件
/usr/local/maven-3.6.3/bin/mvn -f ./pom.xml clean install -Dmaven.test.skip=true
#登陸 Harbor倉庫
docker login 192.168.0.10:1180 -u binghe -p Binghe123
#上傳鏡像到Harbor倉庫
docker push 192.168.0.10:1180/test/test-starter:1.0.0
#中止並刪除K8S集羣中運行的
/usr/bin/kubectl delete -f test.yaml
#將Docker鏡像從新發布到K8S集羣
/usr/bin/kubectl apply -f test.yaml
相關文章
相關標籤/搜索