在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
环境搭建概述亲爱的家人们可以到链接:http://xiazai.ogeek.net/202105/yuanma/javayaml_ogeek.rar 下载所需要的yaml文件。 1.K8S是什么?K8S全称是Kubernetes,是一个全新的基于容器技术的分布式架构领先方案,基于容器技术,目的是实现资源管理的自动化,以及跨多个数据中心的资源利用率的最大化。 如果我们的系统设计遵循了kubernetes的设计思想,那么传统系统架构中那些和业务没有多大关系的底层代码或功能模块,都可以使用K8S来管理,我们不必再费心于负载均衡的选型和部署实施问题,不必再考虑引入或自己开发一个复杂的服务治理框架,不必再头疼与服务监控和故障处理模块的开发。总之,使用kubernetes提供的解决方案,会大大减少开发成本,同时可以将精力更加集中于业务本身,而且由于kubernetes提供了强大的自动化机制,所以系统后期的运维难度和运维成本大幅降低。 2.为什么要用K8S?Docker 这个新兴的容器化技术当前已经被很多公司所采用,其从单机走向集群已成必然,而云计算的蓬勃发展正在加速这一进程。Kubernetes 作为当前唯一被业界广泛认可和看好的 Docker 分布式系统解决方案。可以预见,在未来几年内,会有大量的新系统选择它,不管是运行在企业本地服务器上还是被托管到公有云上。 3.使用K8S有哪些好处?使用Kubernetes就是在全面部署微服务架构。微服务架构的核心就是将一个巨大的单体应用分解为很多小的互相连接的微服务,一个微服务背后可能有多个实例副本在支撑,副本的数量可能会随着系统的负荷变化而进行调整,内嵌的负载均衡器在 k8s 平台中有多个实例副本在支撑,副本的数量可能会随着系统的负荷变化而进行调整,内嵌的负载均衡器 在k8s 平台中发挥了重要的作用。微服务架构使得每个服务都可以由专门的开发团队来开发,开发者可以自由选择开发技术,这对于大规模团队来说很有价值。另外,每个微服务独立开发、升级、扩展,使得系统具备很高的稳定性和快速迭代进化能力。 4.环境构成整套环境的搭建包含:Docker环境的搭建、docker-compose环境的搭建、K8S集群的搭建、GitLab代码仓库的搭建、SVN仓库的搭建、Jenkins自动化部署环境的搭建、Harbor私有仓库的搭建。 本文档中,整套环境的搭建包括:
服务器规划
|
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 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
本文档基于Docker 19.03.8 版本搭建Docker环境。
在所有服务器上创建install_docker.sh脚本,脚本内容如下所示。
#使用阿里云镜像中心 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
Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。
注意:在每台服务器上安装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
#赋予docker-compose可执行权限 chmod a+x /usr/local/bin/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
Kubernetes是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。
本文档基于K8S 1.8.12版本来搭建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
只在test10服务器上执行的操作。
注意:下面的命令需要在命令行手动执行。
# 只在 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
在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
(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>
(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
在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 节点。
针对所有的 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。
在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参数可以输出更多的信息。
Master 节点的 IP 地址发生变化,导致 worker 节点不能启动。需要重新安装K8S集群,并确保所有节点都有固定的内网 IP 地址。
重启服务器后使用如下命令查看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
作为反向代理将外部流量导入集群内部,将 Kubernetes 内部的 Service 暴露给外部,在 Ingress 对象中通过域名匹配 Service,这样就可以直接通过域名访问到集群内部的服务了。相对于 traefik 来说,nginx-ingress 性能更加优秀。
注意:在Master节点(test10服务器上执行)
创建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
创建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
主要是用来用于暴露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
查看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,如下所示。
GitLab是由GitLabInc.开发,使用MIT许可证的基于网络的Git仓库管理工具,且具有Wiki和issue跟踪功能。使用Git作为代码管理工具,并在此基础上搭建起来的web服务。
注意:在Master节点(test10服务器上执行)
创建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
创建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
创建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
(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: [email protected] - 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
查看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完成。
Habor是由VMWare公司开源的容器镜像仓库。事实上,Habor是在Docker Registry上进行了相应的企业级扩展,从而获得了更加广泛的应用,这些新的企业级特性包括:管理用户界面,基于角色的访问控制 ,AD/LDAP集成以及审计日志等,足以满足基本企业需求。
注意:这里将Harbor私有仓库安装在Master节点(test10服务器)上,实际生产环境中建议安装在其他服务器。
wget https://github.com/goharbor/harbor/releases/download/v1.10.2/harbor-offline-installer-v1.10.2.tgz
tar -zxvf harbor-offline-installer-v1.10.2.tgz
解压成功后,会在服务器当前目录生成一个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"] }
配置完成后,输入如下命令即可安装并启动Harbor
[root@binghe harbor]# ./install.sh
安装成功后,在浏览器地址栏输入http://192.168.0.10:1180打开链接,输入用户名admin和密码binghe123,登录系统。
接下来,我们选择用户管理,添加一个管理员账户,为后续打包Docker镜像和上传Docker镜像做准备。
密码为Binghe123。点击确,此时,账户binghe还不是管理员,此时选中binghe账户,点击“设置为管理员”。
此时,binghe账户就被设置为管理员了。到此,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是一个开源的、提供友好操作界面的持续集成(CI)工具,起源于Hudson(Hudson是商用的),主要用于持续、自动的构建/测试软件项目、监控外部任务的运行(这个比较抽象,暂且写上,不做解释)。Jenkins用Java语言编写,可在Tomcat等流行的servlet容器中运行,也可独立运行。通常与版本管理工具(SCM)、构建工具结合使用。常用的版本控制工具有SVN、GIT,构建工具有Maven、Ant、Gradle。
使用 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
在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
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
创建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"] v
请发表评论