01-k8s集群搭建 安装KubeSphere
前言
旧游无处不堪寻,无寻处,未有少年心
1.k8s简介
简介
Kubernetes 简称 k8s。是用于自动部署,扩展和管理容器化应用程序的开源系统。
中文官网:https://kubernetes.io/zh/
中文社区:https://www.kubernetes.org.cn/
官方文档:https://kubernetes.io/zh/docs/home/
社区文档:http://docs.kubernetes.org.cn/
部署方式的进化
[概述 | Kubernetes]:https://kubernetes.io/zh-cn/docs/concepts/overview/

Docker Swarm

k8s调度、k8s自动恢复、k8s水平伸缩

2.k8s架构原理&核心概念
Kubernetes 集群所需的各种组件

整体主从方式


Master 节点架构

-
kube-apiserver- 对外暴露 K8S 的 api 接口,是外界进行资源操作的
- 提供认证、授权、访问控制、API 注册和发现等机制
-
etcd- etcd 是兼具一致性和高可用性的键值数据库,可以作为保存 Kubernetes 所有集 群数据的后台数据库。
- Kubernetes 集群的 etcd 数据库通常需要有个备份计划。
-
kube-scheduler- 主节点上的组件,该组件监视那些新创建的未指定运行节点的 Pod,并选择节点 让 Pod 在上面运行。
- 所有对 k8s 的集群操作,都必须经过主节点进行调度。
-
kube-controller-manage - 在主节点上运行控制器的组件
- 这些控制器包括:
- Node 控制器:负责在节点出现故障时进行通知和响应。
- Job 控制器:监测代表一次性任务的 Job 对象,然后创建 Pod 来运行这些任务直至完成。
- EndpointSlice 控制器:填充 EndpointSlice 对象(以提供 Service 和 Pod 之间的链接)。
- ServiceAccount 控制器:为新的命名空间创建默认的 ServiceAccount。
Node 节点架构
![image-20240828105859986]()
-
kubelet- 一个在集群中每个节点上运行的代理。它保证容器都运行在 Pod 中。
- 负责维护容器的生命周期,同时也负责 Volume(CSI)和网络(CNI)的管理;
-
kube-proxy- 负责为 Service 提供 cluster 内部的服务发现和负载均衡;
-
容器运行环境(Container Runtime)- 容器运行环境是负责运行容器的软件。
- Kubernetes 支持许多容器运行环境,例如 containerd、 CRI-O 以及 Kubernetes CRI (容器运行环境接口)]的其他任何实现。
-
fluentd- 是一个守护进程,它有助于提供集群层面日志 集群层面的日
概念

- Container:容器,可以是 docker 启动的一个容器。
- Pod:
- k8s 使用 Pod 来组织一组容器。
- 一个 Pod 中的所有容器共享同一网络。
- Pod 是 k8s 中的最小部署。
- Volume
- 声明在 Pod 容器中可访问的文件
- 可以被挂载在 Pod 中一个或多个容器指定路劲下
- 支持多种后端存储抽象(本地存储,分布式存储,云存 储…)

- Controllers:更高层次对象,部署和管理 Pod;
- ReplicaSet:确保预期的 Pod 副本数量
- Deplotment:无状态应用部署
- StatefulSet:有状态应用部署。
- DaemonSet:确保所有 Node 都运行一个指定 Pod
- Job:一次性任务
- Cronjob:定时任务
- Deployment
- 定义一组 Pod 的副本数目、版本等。
- 通过控制器(Controller)维持 Pod 数目(自动回 复失败的 Pod)。
- 通过控制器以指定的策略控制版本(滚动升级,回滚等)。

- Service
- 定义一组 Pod 的访问策略。
- Pod 的负载均衡,提供一个或者多个 Pod 的稳定 访问地址。
- 支持多种方式(ClusterIP、NodePort、LoadBalance)

- Label:标签,用于对象资源的查询,筛选。

- Namespace:命名空间,逻辑隔离
- 一个集群内部的逻辑隔离机制(鉴权,资源)
- 每个资源都属于一个 namespace
- 同一个 namespace 所有资源名不能重复
- 不同 namespace 可以资源名重复
- API
- 我们通过 kubernetes 的 API 来操作整个集群。
- 可以通过 kubectl、ui、curl 最终发送 http+json/yaml 方式的请求给 API Server,然后控制 k8s 集群。
- k8s 里的所有的资源对象都可以采用 yaml 或 JSON 格式的文件定义或描述
3.k8s-集群搭建
3.1环境准备
我这里使用的是vmware搭建的centos7环境,可以参考我之前的文章
https://www.cnblogs.com/pengboke/p/18051066
3.2创建三个虚拟机
BUG:Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=7&arch=x86_64&repo=os&infra=stock error was
14: curl#6 - "Could not resolve host: mirrorlist.centos.org; 未知的错误"
参考地址:https://www.cnblogs.com/zengzuo613/p/18292809
打开/etc/yum.repos.d/CentOS-Vault.repo
vim /etc/yum.repos.d/CentOS-Vault.repo
在 CentOS-Vault.repo 添加如下配置,以启用 CentOS 7 的存档仓库,添加配置如下:
# 文件路径 /etc/yum.repos.d/CentOS-Vault.repo
# Vault
[Vault-base]
name=Vault - CentOS-$releasever - Base
baseurl=http://vault.centos.org/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-$releasever
[Vault-updates]
name=Vault - CentOS-$releasever - Updates
baseurl=http://vault.centos.org/centos/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-$releasever
[Vault-extras]
name=Vault - CentOS-$releasever - Extras
baseurl=http://vault.centos.org/centos/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-$releasever

使用 enabled=0 禁用 CentOS-Base.repo 中的所有仓库,修改后配置如下:
vim /etc/yum.repos.d/CentOS-Base.repo
[base]
name=CentOS-$releasever - Base
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

特别说明: CentOS 7 各子版本中,$releasever 值都为 7。具体原因请看:releaseve 变量详解。
清除 YUM 缓存,如有需要可再生成新的缓存
yum clean all ; yum makecache

验证方法
yum repolist

VMware克隆
之前我已经创建了一个虚拟机,并且拍摄了快照


修改ip
vim /etc/sysconfig/network-scripts/ifcfg-ens33

重启网络服务,查看ip是否配置成功
service network restart
ifconfig

安装docker
官方文档:https://docs.docker.com/engine/install/centos/
# 如果系统中已经存在旧的Docker,则先卸载
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 安装一个yum工具
yum install -y yum-utils
# 配置Docker的yum源 aliyun
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装Docker
yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
配置镜像加速
# 配置源文件
cat <<EOF > /etc/docker/daemon.json
{
"registry-mirrors": [
"https://registry.docker-cn.com",
"https://docker.mirrors.ustc.edu.cn",
"https://mirror.baidubce.com",
"https://80cebfmn.mirror.aliyuncs.com",
"https://cr.console.aliyun.com",
"https://hub-mirror.c.163.com",
"http://mirrors.tuna.tsinghua.edu.cn",
"http://mirrors.aliyun.com"
]
}
EOF
常用命令
# 重新启动
systemctl daemon-reload
systemctl restart docker
# 设置开机自启
systemctl enable docker

给k8s-01拍摄快照
当前状态是docker已安装完成,在克隆节点时不用再安装

然后创建k8s-02、k8s-03节点

k8s-02修改ip为192.168.188.182,修改k8s-02时关闭k8s-01
# 修改ip
vim /etc/sysconfig/network-scripts/ifcfg-ens33
# 重启网卡
service network restart

k8s-03修改ip为192.168.188.183,修改k8s-03时关闭k8s-02

三个虚拟机创建完毕

3.3NAT网络和前置环境
修改三台主机名
打开hosts文件
vi /etc/hosts
修改
# ip + 机器别名
cat >> /etc/hosts << EOF
192.168.188.181 k8s-01
192.168.188.182 k8s-02
192.168.188.183 k8s-03
EOF

ping一下,三台都能互相ping通即可
ping k8s-01

BUG:unable to load client CA file /etc/kubernetes/pki/ca.crt: open /etc/kubernetes/pki/ca.crt: no such file or directory
检查 /etc/kubernetes/pki/ 目录下是否存在 ca.crt 文件:
ls -l /etc/kubernetes/pki/ca.crt
重新初始化 Kubernetes
sudo kubeadm reset
3.4安装Docker、kubelet、kubeadm、kubectl
检查操作系统的版本
检查操作系统的版本(要求操作系统的版本至少在7.5以上):
cat /etc/redhat-release

关闭防火墙和禁止防火墙开机启动
关闭防火墙:
systemctl stop firewalld
禁止防火墙开机启动:
systemctl disable firewalld

设置主机名
语法:
hostnamectl set-hostname <hostname>
命令
# 192.168.188.181主机
hostnamectl set-hostname k8s-01
# 192.168.188.182主机
hostnamectl set-hostname k8s-02
# 192.168.188.183主机
hostnamectl set-hostname k8s-03

主机名解析
cat >> /etc/hosts << EOF
192.168.188.181 k8s-01
192.168.188.182 k8s-02
192.168.188.183 k8s-03
EOF

时间同步
kubernetes要求集群中的节点时间必须精确一致,所以在每个节点上添加时间同步:
安装ntpdate
yum install ntpdate -y
设置时间
ntpdate time.windows.com

关闭selinux
查看selinux是否开启:
getenforce
永久关闭selinux,需要重启:
sed -i 's/enforcing/disabled/' /etc/selinux/config
临时关闭selinux,重启之后,无效:
setenforce 0

关闭swap分区
永久关闭swap分区,需要重启:
sed -ri 's/.*swap.*/#&/' /etc/fstab
临时关闭swap分区,重启之后,无效:
swapoff -a

将桥接的IPv4流量传递到iptables的链
在每个节点上将桥接的IPv4流量传递到iptables的链:
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
vm.swappiness = 0
EOF
加载br_netfilter模块
modprobe br_netfilter
查看是否加载
lsmod | grep br_netfilter
生效
sysctl --system

开启ipvs
在kubernetes中service有两种代理模型,一种是基于iptables,另一种是基于ipvs的。ipvs的性能要高于iptables的,但是如果要使用它,需要手动载入ipvs模块。
在每个节点安装ipset和ipvsadm:
yum -y install ipset ipvsadm
在所有节点执行如下脚本:
cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
授权、运行、检查是否加载:
chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4
检查是否加载:
lsmod | grep -e ipvs -e nf_conntrack_ipv4

重启三台机器
reboot
安装Docker
# 卸载docker
# sudo yum remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
# 第一步:安装docker
yum -y install docker-ce-18.06.3.ce-3.el7
# 第二步:配置docker镜像源
cat <<EOF > /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": [
"https://du3ia00u.mirror.aliyuncs.com",
"https://registry.docker-cn.com",
"https://docker.mirrors.ustc.edu.cn",
"https://mirror.baidubce.com",
"https://80cebfmn.mirror.aliyuncs.com",
"https://cr.console.aliyun.com",
"https://hub-mirror.c.163.com",
"http://mirrors.tuna.tsinghua.edu.cn",
"http://mirrors.aliyun.com"
],
"live-restore": true,
"log-driver":"json-file",
"log-opts": {"max-size":"500m", "max-file":"3"},
"storage-driver": "overlay2"
}
EOF
# 第三步:重启
# 开机自启动
systemctl enable docker && systemctl start docker
# 验证版本
docker version

BUG:启动docker的时候:Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details.
原因可能是低版本的docker配置文件不支持json
[root@k8s-02 ~]# cd /etc/docker
[root@k8s-02 docker]# ls
daemon.json key.json
[root@k8s-02 docker]# mv daemon.json daemon.conf

添加阿里云的YUM软件源
由于kubernetes的镜像源在国外,非常慢,这里切换成国内的阿里云镜像源:
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

安装kubeadm、kubelet和kubectl
由于版本更新频繁,这里指定版本号部署:
yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0

为了实现Docker使用的cgroup drvier和kubelet使用的cgroup drver一致,建议修改"/etc/sysconfig/kubelet"文件的内容:
vim /etc/sysconfig/kubelet

修改:
# 修改
KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"
KUBE_PROXY_MODE="ipvs"

设置为开机自启动即可,由于没有生成配置文件,集群初始化后自动启动:
systemctl enable kubelet

查看k8s所需镜像
kubeadm config images list

部署k8s的Master节点
部署k8s的Master节点(192.168.188.181)
如果失败需要重新启动时kubeadm reset,是在不行,上面再检查一下
如果kubeadm reset失败,需要删除etcd服务,执行一下命令sudo rm -rf /var/lib/etcd
# 由于默认拉取镜像地址k8s.gcr.io国内无法访问,这里需要指定阿里云镜像仓库地址
kubeadm init \
--apiserver-advertise-address=192.168.188.181 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.18.0 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16
根据提示消息,在Master节点上使用kubectl工具:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

部署k8s的Node节点
根据提示,在192.168.188.182和192.168.188.183上添加如下的命令:
kubeadm join 192.168.188.181:6443 --token qq2whn.e9i313jry0xc2uj5 \
--discovery-token-ca-cert-hash sha256:90396f2d1aecf4bc04b2f22a754a7e16fdbcf3b8a9c40c45befd210c1b63b34f
默认的token有效期为2小时,当过期之后,该token就不能用了,这时可以使用如下的命令创建token:
kubeadm token create --print-join-command
生成一个永不过期的token
kubeadm token create --ttl 0 --print-join-command
部署CNI网络插件
根据提示,在Master节点上使用kubectl工具查看节点状态:
kubectl get nodes
kubernetes支持多种网络插件,比如flannel、calico、canal等,任选一种即可,本次选择flannel,如果网络不行,可以使用本人提供的[📎kube-flannel.yml],当然,你也可以安装calico,请点这里[📎calico.yaml],推荐安装calico。
可以使用已经下载好的calico.yaml,这个执行完成就不用执行下面的kube-flannel.yml了
kubectl apply -f kube-flannel.yml

在Master节点上获取flannel配置文件(可能会失败,如果失败,请下载到本地,然后安装):
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
使用配置文件启动flannel:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

BUG:如果插件状态不是running
查看那些插件没有running
kubectl get pods -n kube-system
使用docker pull 看看能不能手动拉取
docker pull
不可以的话检查一下/etc/docker/daemon.json
vim /etc/docker/daemon.json
BUG:failed to find plugin "flannel" in path [/opt/cni/bin]]
flannel插件安装完成后,所有状态都是Running,但节点k8s-02 、k8s-03还是NotReady

查看k8s-02日志,大致意思是找不到flannel
journalctl -f -u kubelet.service

解决办法:把k8s-01下的/opt/cni/bin/flannel同步到k8s-02、k8s-03
# 把flannel插件同步到k8s-02
scp /opt/cni/bin/flannel root@k8s-02:/opt/cni/bin/
# 把flannel插件同步到k8s-03
scp /opt/cni/bin/flannel root@k8s-03:/opt/cni/bin/
# 重启k8s-02和k8s-03
systemctl restart kubelet
# 再次查看节点状态
kubectl get nodes

查看部署CNI网络插件进度:
kubectl get pods -n kube-system

再次在Master节点使用kubectl工具查看节点状态:
kubectl get nodes

查看集群健康状况:
kubectl get cs

显示当前 Kubernetes 集群的基本信息,包括主控组件(如 Kubernetes API server)的访问地址和相关服务的地址
kubectl cluster-info

常用命令
调试的时候经常用到的命令
rm flannel.tar.gz
curl -L https://github.com/flannel-io/flannel/releases/download/v0.17.1/flannel-v0.17.1-linux-amd64.tar.gz -o flannel.tar.gz
tar -xzf flannel.tar.gz -C /opt/cni/bin
journalctl -f -u kubelet.service
watch kubectl get pod -n kube-system -o wide
kubectl describe pod calico-kube-controllers-7dbc97f587-m9tqq -n kube-system
kubectl describe pod kube-flannel-ds-7pwlg -n kube-system
kubectl apply -f kube-flannel.yml
kubectl delete -f kube-flannel.yml
kubectl apply -f calico.yaml
kubectl delete -f calico.yaml
docker pull mirror.baidubce.com/nginx:latest
cat <<EOF > /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": [
"https://du3ia00u.mirror.aliyuncs.com",
"https://registry.docker-cn.com",
"https://mirror.baidubce.com",
"https://80cebfmn.mirror.aliyuncs.com",
"https://cr.console.aliyun.com",
"https://hub-mirror.c.163.com",
"http://mirrors.tuna.tsinghua.edu.cn",
"http://mirrors.aliyun.com",
"https://docker.mirrors.ustc.edu.cn"
],
"live-restore": true,
"log-driver":"json-file",
"log-opts": {"max-size":"500m", "max-file":"3"},
"storage-driver": "overlay2"
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
systemctl status docker
systemctl restart docker
docker pull nginx:latest
docker pull 80cebfmn.mirror.aliyuncs.com/nginx:latest
docker pull mirrors.cloud.aliyuncs.com/calico/kube-controllers:v3.17.1
docker pull 80cebfmn.mirror.aliyuncs.com/calico/kube-controllers:v3.17.1
kubectl logs -n kube-system coredns-7ff77c879f-l6xfh
kubectl describe pod coredns-7ff77c879f-l6xfh -n kube-system
docker load --input flannel-0.11.0-amd64.tar #导入镜像
cat /etc/hosts
3.5卸载kubelet、kubeadm、kubectl
首先,停止并禁用相关服务
sudo systemctl stop kubelet
sudo systemctl stop docker
sudo systemctl stop containerd
sudo systemctl disable kubelet
sudo systemctl disable docker
sudo systemctl disable containerd
卸载软件包
sudo yum remove -y kubelet kubeadm kubectl
删除 Kubernetes 配置文件和数据目录
sudo rm -rf /etc/kubernetes
sudo rm -rf /var/lib/kubelet
sudo rm -rf /var/lib/etcd
sudo rm -rf /var/lib/kube-proxy
sudo rm -rf /var/lib/cni
sudo rm -rf /var/run/kubernetes
删除containerd
sudo rm -rf /var/lib/containerd
安装时清空环境
sudo rm -rf /etc/kubernetes
sudo rm -rf /var/lib/etcd/*
4.8k8s-入门
4.1基本操作体验
BUG:docker下载镜像一直失败
更新镜像地址,然后重启docker
# dockera安装失败,可以更新镜像源地址
cat <<EOF > /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors":[
"https://x9r52uz5.mirror.aliyuncs.com",
"https://dockerhub.icu",
"https://docker.chenby.cn",
"https://docker.1panel.live",
"https://docker.awsl9527.cn",
"https://docker.anyhub.us.kg",
"https://dhub.kubesre.xyz"
],
"live-restore": true,
"log-driver":"json-file",
"log-opts": {"max-size":"500m", "max-file":"3"},
"storage-driver": "overlay2"
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

安装nginx
安装nginx
# 删除deployment命令,如果已创建需要删除
# kubectl delete deployment nginx
kubectl create deployment nginx --image=nginx:latest

查看pod信息
# 获取当前命名空间中的所有 Pod 的列表
kubectl get pods
# 获取当前命名空间中的所有 Pod 的详细信息
kubectl get pods -o wide
# 获取当前命名空间中所有类型的资源的列表
kubectl get all

模拟服务宕机,容灾恢复
刚才nginx安装在k8s-02,我们关闭k8s-02

k8s-02节点停止运行nginx,k8s-03节点重新运行nginx
# 获取当前命名空间中的所有 Pod 的列表
kubectl get pods
# 获取当前命名空间中的所有 Pod 的详细信息
kubectl get pods -o wide
# 获取当前命名空间中所有类型的资源的列表
kubectl get all

暴露访问端口
Pod 的 80 映射容器的 80;service 会代理 Pod 的 8080
# 删除命令,如果已创建需要删除
# kubectl delete service nginx
kubectl expose deployment nginx --port=80 --target-port=8080 --type=NodePort

查看集群信息
# 显示k8s所有服务
kubectl get svc
# 在get svc显示更详细信息
kubectl get svc -o wide
# 显示集群中所有的 Pod
kubectl get pods -o wide

获取 k8s集群中各种资源
kubectl get all

发现外部服务端口31050,访问http://192.168.188.182:31050/
动态扩容测试
# 查看集群中所有的部署
kubectl get deployment
# 将 nginx 部署的副本数(Pods 数量)调整为 3 个
kubectl scale --replicas=3 deployment nginx
# 显示集群中所有的 Pod
kubectl get pods -o wide
# 显示所有服务(Services)及其详细信息
kubectl get svc -o wide
# 将 nginx 部署的副本数调整为 1 个
kubectl scale --replicas=1 deployment nginx
# 显示集群中所有的 Pod
kubectl get pods -o wide
查看部署

将nginx扩容3个

k8s-02部署了2个,k8s-03部署了1个

查看服务

将nginx缩容回1个

只有k8s-03运行了1个

删除
kubectl get all
# 删除部署
kubectl delete deployment nginx
# 删除服务
kubectl delete service nginx

4.2yaml&基本使用
kubectl
kubectl 文档:https://kubernetes.io/zh-cn/docs/reference/kubectl/
资源类型:https://kubernetes.io/zh-cn/docs/reference/kubectl/#资源类型
格式化输出:https://kubernetes.io/zh-cn/docs/reference/kubectl/#格式化输出
常用操作:https://kubernetes.io/zh-cn/docs/reference/kubectl/#示例-常用操作
命令参考:https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands
yaml 语法
yml 模版

Deployment服务yaml文件
部署nginx命令,查看帮助
kubectl create deployment nginx --image=nginx:latest --help

生成部署nginx的yaml
kubectl create deployment nginx --image=nginx:latest --dry-run -o yaml
生成并查看nginx.yaml
# 进入k8s/
cd k8s/
# 生成nginx.yaml
kubectl create deployment nginx --image=nginx:latest --dry-run -o yaml > nginx.yaml
# 编辑nginx.yaml
vim nginx.yaml


执行nginx.yaml
kubectl apply -f nginx.yaml
kubectl get pods

Service服务yaml文件
kubectl expose deployment nginx --port=80 --target-port=8080 --type=NodePort --dry-run -o yaml

Pod服务yaml文件
查看Pod服务
kubectl get pods
kubectl get pod nginx-674ff86d-4phzq
kubectl get pod nginx-674ff86d-4phzq -o yaml

执行pod.yaml
# 删除pods
# kubectl delete pod nginx-new
kubectl get pod nginx-674ff86d-4phzq -o yaml > mypod.yaml
vim mypod.yaml
kubectl apply -f mypod.yaml
kubectl get pods
mypod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
app: nginx-new
name: nginx-new
namespace: default
spec:
containers:
- image: nginx:latest
imagePullPolicy: IfNotPresent
name: nginx-new


4.3Pod、Service等概念
Pod&Controller
官方文档:https://kubernetes.io/zh-cn/docs/reference/kubectl/#资源类型
Pod 和控制器
控制器可以为您创建和管理多个 Pod,管理副本和上线,并在集群范围内提供自修复能力。 例如,如果一个节点失败,控制器可以在不同的节点上调度一样的替身来自动替换 Pod。 包含一个或多个 Pod 的控制器一些示例包括:
- Deployment
- StatefulSet
- DaemonSet
控制器通常使用您提供的 Pod 模板来创建它所负责的 Pod
Deployment&Service

Service 的意义
统一应用访问入口;
Service 管理一组 Pod。 防止 Pod 失联(服务发现)、定义一组 Pod 的访问策略。
现在 Service 我们使用 NodePort 的方式暴露,这样访问每个节点的端口,都可以访问到这 个 Pod,如果节点宕机,就会出现问题。
labels and selectors

4.4Ingress
使用yaml安装tomcat和nginx
清除环境
kubectl get all
kubectl delete deployment.apps/nginx
kubectl delete pod/nginx-new

tomcat事例
kubectl create deployment tomcat --image=tomcat:8 --dry-run=client -o yaml > tomcat-deployment.yaml
kubectl apply -f tomcat-deployment.yaml
kubectl get all
kubectl expose deployment tomcat --port=80 --target-port=8080 --type=NodePort --dry-run=client -o yaml
kubectl get all
kubectl delete deployment.apps/tomcat
kubectl apply -f tomcat-deployment.yaml
tomcat-deployment.yaml
cat <<EOF > tomcat-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: tomcat
name: tomcat
spec:
replicas: 3
selector:
matchLabels:
app: tomcat
template:
metadata:
labels:
app: tomcat
spec:
containers:
- image: tomcat:8
name: tomcat
---
apiVersion: v1
kind: Service
metadata:
labels:
app: tomcat
name: tomcat
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: tomcat
type: NodePort
EOF

nginx事例
kubectl create deployment nginx --image=nginx:latest --dry-run=client -o yaml > nginx-deployment.yaml
kubectl apply -f nginx-deployment.yaml
kubectl get all
kubectl expose deployment nginx --port=80 --target-port=8080 --type=NodePort --dry-run=client -o yaml
kubectl get all
kubectl delete deployment.apps/nginx
kubectl apply -f nginx-deployment.yaml
nginx-deployment.yaml
cat <<EOF > nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:latest
name: nginx
---
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
name: nginx
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: nginx
type: NodePort
EOF

安装Ingress
将ingress-controller.yaml上传到服务器,安装Ingress
kubectl apply -f ingress-controller.yaml
kubectl get pods --all-namespaces

创建 Ingress 规则
kubectl apply -f ingress-demo.yaml
ingress-demo.yaml
cat <<EOF > ingress-demo.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: web
spec:
rules:
- host: tomcat.peng.com
http:
paths:
- backend:
serviceName: tomcat
servicePort: 80
EOF
我安装的是tomcat8,发现没有默认的index.html
# 查看所有服务
kubectl get all
# 进入容器,给一个容器创建ROOT/index.html
# kubectl exec -it tomcat-6fbdf4497-5vpbz -- /bin/bash
# kubectl exec -it tomcat-6fbdf4497-xbnmd -- /bin/bash
kubectl exec -it tomcat-6fbdf4497-4dn6z -- /bin/bash
cd $CATALINA_HOME/webapps/
mkdir ROOT
cd ROOT
cat <<EOF > index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Tomcat</title>
</head>
<body>
<h1>Tomcat is Running!</h1>
</body>
</html>
EOF
cd $CATALINA_HOME/webapps/ROOT

进入3个容器好,创建默认页

配置SwitchHosts
192.168.188.182 tomcat.peng.com

访问http://192.168.188.182:31123、http://192.168.188.183:31123、tomcat.peng.com

模拟宕机
有2个tomcat安装在k8s-03,关闭k8s-03
kubectl get pods -o wide

依旧可以访问http://tomcat.peng.com/

打包下载的tomcat镜像
docker save -o tomcat8.tar tomcat:8
docker load -i tomcat8.tar
5.kubesphere-安装
5.1前置环境
简介
KubeSphere 是一款面向云原生设计的开源项目,在目前主流容器调度平台 Kubernetes 之 上构建的分布式多租户容器管理平台,提供简单易用的操作界面以及向导式操作方式,在降 低用户使用容器调度平台学习成本的同时,极大降低开发、测试、运维的日常工作的复杂度。
版本文档:https://v3-1.docs.kubesphere.io/zh/docs/installing-on-kubernetes/introduction/prerequisites/
选择自己k8s合适的版本,我的k8s版本是v1.18.0

准备工作

k8s版本问题,我k8s集群版本是v1.18.0,所以我安装KubeSphere v3.1.1
kubectl version

可用 CPU > 1 核;内存 > 2 G
free -g

检查集群中是否有默认 StorageClass(准备默认 StorageClass 是安装 KubeSphere 的前提条件)
对于本地虚拟机环境,常见的选择包括:
- HostPath(仅用于测试)
- 用途:本地开发、测试
- 优点:简单易用,支持本地磁盘存储
- NFS(适合网络共享)
- 用途:简单的测试和实验
- 优点:无需额外安装,只依赖本地文件系统
- 缺点:仅适用于单节点或测试环境,数据不会在多个节点间共享
- Local Path(用于本地磁盘)
- 用途:多个节点间共享存储
- 优点:支持网络共享,适合在多个虚拟机之间共享数据
- 缺点:需要额外的 NFS 服务器配置

安装helm
# 下载 Helm
curl -L https://get.helm.sh/helm-v3.15.4-linux-amd64.tar.gz -o helm-v3.15.4-linux-amd64.tar.gz
# 检查文件完整性
file helm-v3.15.4-linux-amd64.tar.gz
# 解压安装包
tar -zxvf helm-v3.15.4-linux-amd64.tar.gz
# 进入该文件夹
cd linux-amd64
# 移动 Helm 可执行文件: 将解压后的 Helm 可执行文件移动到系统的全局路径
sudo mv helm /usr/local/bin/
# 查看 Helm 版本
helm version
# 添加 Helm 仓库
helm repo add stable https://charts.helm.sh/stable
helm repo update

安装OpenEBS
# 添加 OpenEBS 的 Helm 仓库
helm repo add openebs https://openebs.github.io/charts/
helm repo update
# 安装 OpenEBS
helm install openebs --namespace openebs --create-namespace openebs/openebs

创建 LocalPV StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: openebs-local
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: openebs.io/local
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
创建 PVC 使用 LocalPV
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: openebs-local-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: openebs-local
执行
vim local-pv-sc.yaml
kubectl apply -f local-pv-sc.yaml
kubectl get sc
vim pvc-local.yaml
kubectl apply -f pvc-local.yaml

部署一个使用 PVC 的 Pod
apiVersion: v1
kind: Pod
metadata:
name: busybox
spec:
containers:
- name: busybox
image: busybox
command:
- sleep
- "3600"
volumeMounts:
- mountPath: "/mnt/disks"
name: openebs-local-vol
volumes:
- name: openebs-local-vol
persistentVolumeClaim:
claimName: openebs-local-pvc
执行
kubectl apply -f busybox-pod.yaml
prometheus-pvc.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: prometheus-pv-0
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /mnt/data/prometheus0
storageClassName: openebs-local
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: prometheus-pv-1
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /mnt/data/prometheus1
storageClassName: openebs-local
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
执行
# 三台主机都需要创建/mnt/data/prometheus0
# 三台主机都需要创建/mnt/data/prometheus1
mkdir -p /mnt/data/prometheus0
mkdir -p /mnt/data/prometheus1
# 三台主机都需要添加权限
# 三台主机都需要添加权限
chmod 777 /mnt/data/prometheus0
chmod 777 /mnt/data/prometheus1
# k8s-01(master)执行
vim prometheus-pvc.yaml
kubectl apply -f prometheus-pvc.yaml
kubectl get pvc -n kubesphere-monitoring-system
kubectl get pods -n kubesphere-monitoring-system
验证
kubectl get sc
kubectl get pv -n kubesphere-monitoring-system
kubectl get pvc -n kubesphere-monitoring-system
kubectl get pods -n kubesphere-monitoring-system
重启kubesphere命令
重启 KubeSphere 的核心组件
kubectl rollout restart deployment ks-apiserver -n kubesphere-system
kubectl rollout restart deployment ks-controller-manager -n kubesphere-system
kubectl rollout restart deployment ks-console -n kubesphere-system
重启 KubeSphere 的其他服务
kubectl get deployments -A | grep kubesphere | awk '{print "kubectl rollout restart deployment " $2 " -n " $1}' | sh
检查服务状态
kubectl get pods -A | grep kubesphere
如果需要,重启整个 KubeSphere 命名空间的 Pod
kubectl delete pod --all -n kubesphere-system
kubectl delete pod --all -n kubesphere-monitoring-system
kubectl delete pod --all -n kubesphere-controls-system
检查集群整体状态
kubectl get pods -A
卸载kubesphere命令
删除namespaces
kubectl get pods --all-namespaces
kubectl delete namespace kubesphere-controls-system --force --grace-period=0
kubectl delete namespace kubesphere-devops-system --force --grace-period=0
kubectl delete namespace kubesphere-monitoring-system --force --grace-period=0
# kubectl delete namespace kubesphere-system --force --grace-period=0
kubectl delete namespace kubesphere-alerting-system --force --grace-period=0
kubectl delete namespace kubesphere-monitoring-system --force --grace-period=0
删掉finalizers
# 编辑命名空间 kubesphere-alerting-system
kubectl edit namespace kubesphere-alerting-system
# 编辑命名空间 kubesphere-controls-system
kubectl edit namespace kubesphere-controls-system
# 编辑命名空间 kubesphere-devops-system
kubectl edit namespace kubesphere-devops-system
# 编辑命名空间 kubesphere-monitoring-system
kubectl edit namespace kubesphere-monitoring-system
5.2最小化安装完成
最小化安装kubesphere
官方地址:https://v2-1.docs.kubesphere.io/docs/zh-CN/appendix/install-openebs/
地址:https://v3-1.docs.kubesphere.io/zh/docs/quick-start/minimal-kubesphere-on-k8s/

# 安装命令
# 可以下载到本地安装 这个过程比较耗时,对网络要求较高
# kubectl apply -f kubesphere-installer.yaml
# kubectl apply -f cluster-configuration.yaml
# 或者远程地址安装 这个过程比较耗时,对网络要求较高
kubectl apply -f https://github.com/kubesphere/ks-installer/releases/download/v3.1.1/kubesphere-installer.yaml
kubectl apply -f https://github.com/kubesphere/ks-installer/releases/download/v3.1.1/cluster-configuration.yaml
kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l app=ks-install -o jsonpath='{.items[0].metadata.name}') -f
kubectl get svc/ks-console -n kubesphere-system
# *************************************************
# 查看和删除命令
kubectl get pods --all-namespaces
kubectl get pods -n kubesphere-monitoring-system
kubectl delete -f kubesphere-installer.yaml
kubectl delete -f cluster-configuration.yaml
kubectl delete pod -n kubesphere-system ks-installer-7bd6b699df-nqxjh
kubectl logs -n kubesphere-system ks-installer-7bd6b699df-nqxjh
BUG:Failed to ansible-playbook result-info.yaml

从你提供的日志来看,KubeSphere 的核心组件 (ks-apiserver、ks-console 和 ks-controller-manager) 无法创建 Pod,因为找不到 kubesphere-system 命名空间中的 kubesphere 服务账户。这是导致 KubeSphere 安装失败的主要原因。
kubectl get events -n kubesphere-system

kubesphere-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: kubesphere
namespace: kubesphere-system
kubesphere-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: kubesphere-rolebinding
namespace: kubesphere-system
subjects:
- kind: ServiceAccount
name: kubesphere
namespace: kubesphere-system
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
执行
kubectl apply -f kubesphere-serviceaccount.yaml
kubectl apply -f kubesphere-rolebinding.yaml
BUG:重置密码
安装成功后,我是用默认的账号登不上

官方提供重置管理员密码命令
官方文档:https://v3-1.docs.kubesphere.io/zh/docs/faq/access-control/forgot-password/

kubectl patch users admin -p '{"spec":{"password":"P@88w0rd"}}' --type='merge' && kubectl annotate users admin iam.kubesphere.io/password-encrypted-
安装完成
总算登录成功,太不容易了

5.3定制化安装&界面介绍
定制化安装
官方地址:https://v3-1.docs.kubesphere.io/zh/docs/pluggable-components/
主要需要DevOps 系统、告警系统
KubeSphere 3.1.1 版本没有集成独立的 Notification 系统(告警通知系统),该功能是在后续版本中引入的。

修改cluster-configuration.yaml

在执行kubesphere-installer.yaml和cluster-configuration.yaml
kubectl apply -f https://github.com/kubesphere/ks-installer/releases/download/v3.1.1/kubesphere-installer.yaml
kubectl apply -f cluster-configuration.yaml
界面介绍
我的3.1.1和2版本有很多区别,自己多点点就可以了

6.kubesphere-进阶
kubesphere成功安装记得备份,拍摄快照,我后面因为k8s内存溢出需要重新搭建环境,还好我在这备份了

6.1建立多租户系统
官方文档:https://v3-1.docs.kubesphere.io/zh/docs/quick-start/create-workspace-and-project/

创建账号
创建user-manager,所有密码为Peng123456

登录user-manager,创建四个账号

ws-manager workspaces-manager 创建和管理所有企业空间。
ws-admin platform-regular 管理指定企业空间中的所有资源(在此示例中,此帐户用于邀请新成员加入该企业空间)。
project-admin platform-regular 创建和管理项目以及 DevOps 工程,并邀请新成员加入项目。
project-regular platform-regular project-regular 将由 project-admin 邀请至项目或 DevOps 工程。该帐户将用于在指定项目中创建工作负载、流水线和其他资源。

创建企业空间
以 ws-manager 身份登录 KubeSphere,它具有管理平台上所有企业空间的权限。在企业空间中,可以看到仅列出了一个默认企业空间 system-workspace,即系统企业空间,其中运行着与系统相关的组件和服务,您无法删除该企业空间。
点击右侧的创建,将新企业空间命名为 peng-mall-workspace,并将用户 ws-admin 设置为企业空间管理员。完成后,点击创建。

以 ws-admin 身份重新登录。在企业空间设置中,选择企业成员,然后点击邀请成员。
邀请 project-admin 和 project-regular 进入企业空间,分别授予 workspace-self-provisioner 和 workspace-viewer 角色,点击确定。
ws-admin workspace-admin 管理指定企业空间中的所有资源(在此示例中,此帐户用于邀请新成员加入企业空间)。
project-admin workspace-self-provisioner 创建和管理项目以及 DevOps 工程,并邀请新成员加入项目。
project-regular workspace-viewer project-regular 将由 project-admin 邀请至项目或 DevOps 工程。该帐户将用于在指定项目中创建工作负载、流水线和其他资源。

创建项目
以 project-admin 身份登录 KubeSphere Web 控制台,在项目管理中,点击创建。
输入项目名称(例如 peng-mall),然后点击确定完成,您还可以为项目添加别名和描述。

邀请 project-regular 至该项目,并授予该用户 operator 角色。请参考下图以了解具体步骤。

创建peng-mall-devops

创建角色
在账户角色右侧点击创建,创建peng-hr用于账户的CRUD

编辑权限

6.2创建WorldPress应用-密钥
官方文档:https://v3-1.docs.kubesphere.io/zh/docs/quick-start/wordpress-deployment/

创建密钥
使用 project-regular 帐户登录 KubeSphere 控制台。访问 peng-mall 的详情页并导航到配置中心。在密钥中,点击右侧的创建。
输入基本信息(例如,将其命名为 mysql-secret)并点击下一步。在下一页中,选择类型为 Opaque(默认),然后点击添加数据来添加键值对。输入如下所示的键 (Key) MYSQL_ROOT_PASSWORD 和值 (Value) 123456,点击右下角 √ 进行确认。完成后,点击创建按钮以继续。
按照以上相同的步骤创建一个名为 wordpress-secret 的 WordPress 密钥,输入键 (Key) WORDPRESS_DB_PASSWORD 和值 (Value) 123456。创建的密钥显示在列表中,如下所示:

创建存储卷
访问存储管理下的存储卷,点击创建。
输入卷的基本信息(例如,将其命名为 wordpress-pvc),然后点击下一步。
在存储卷设置中,需要选择一个可用的存储类型,并设置访问模式和存储卷容量。您可以直接使用如下所示的默认值,点击下一步继续。

6.3创建WorldPress应用-创建容器
添加 MySQL 后端组件
官方文档:https://v3-1.docs.kubesphere.io/zh/docs/quick-start/wordpress-deployment/#步骤-3创建应用程序

导航到应用负载下的应用,选择自制应用,再点击构建自制应用。

输入基本信息(例如,在应用名称一栏输入 wordpress),然后点击下一步。

在服务组件中,点击添加服务以在应用中设置组件。
设置组件的服务类型为有状态服务。

输入有状态服务的名称(例如 mysql)并点击下一步。

在容器镜像中,点击添加容器镜像。
在搜索框中输入 mysql:5.6,按下回车键,然后点击使用默认端口。由于配置还未设置完成,请不要点击右下角的 √ 按钮。

在高级设置中,请确保内存限制不小于 1000 Mi,否则 MySQL 可能因内存不足而无法启动。

设置mysql的CPU和内存

配置环境变量
https://hub.docker.com/_/mysql

向下滚动到环境变量,点击引用配置文件或密钥。输入名称 MYSQL_ROOT_PASSWORD,然后选择资源 mysql-secret 和前面步骤中创建的密钥 MYSQL_ROOT_PASSWORD,完成后点击 √ 保存配置,最后点击下一步继续。

添加存储卷模板
https://hub.docker.com/_/mysql

选择挂载存储中的添加存储卷模板,输入存储卷名称 (mysql) 和挂载路径(模式:读写,路径:/var/lib/mysql)的值,如下所示:

添加WordPress前端组件
官方地址:https://v3-1.docs.kubesphere.io/zh/docs/quick-start/wordpress-deployment/#步骤-3创建应用程序

再次点击添加服务,这一次选择无状态服务。

输入名称 wordpress 并点击下一步。

与上述步骤类似,点击添加容器镜像,在搜索栏中输入 wordpress:4.8-apache 并按下回车键,然后点击使用默认端口。

配置WordPress环境变量
官方地址:https://hub.docker.com/_/wordpress

对于此处添加的第二个环境变量,该值必须与创建 MySQL 有状态服务设置的名称完全相同。否则,WordPress 将无法连接到 MySQL 对应的数据库。

向下滚动到环境变量,点击引用配置文件或密钥。这里需要添加两个环境变量,请根据以下截图输入值:
- 对于
WORDPRESS_DB_PASSWORD,请选择在步骤 1 中创建的wordpress-secret和WORDPRESS_DB_PASSWORD。 - 点击添加环境变量,分别输入
WORDPRESS_DB_HOST和mysql作为键 (Key) 和值 (Value)。

在挂载存储中,点击添加存储卷,并选择已有存储卷。

查看wordpress容器配置的数据卷在/var/www/html

选择上一步创建的 wordpress-pvc,将模式设置为读写,并输入挂载路径 /var/www/html。点击 √ 保存,再点击下一步继续。

现在,前端组件也已设置完成。点击下一步继续。

您可以在这里设置路由规则(应用路由 Ingress),也可以直接点击创建。

创建后,应用将显示在下面的列表中。
6.4创建WorldPress应用-外网访问
验证资源
在工作负载中,分别检查部署和有状态副本集中 wordpress-v1 和 mysql-v1 的状态。如果它们的运行状态如下图所示,就意味着 WordPress 已经成功创建。


通过 NodePort 访问 WordPress
若要在集群外访问服务,请首先导航到服务。点击 wordpress 右侧的三个点后,选择编辑外网访问

在访问方式中选择 NodePort,然后点击确定。

点击服务进入详情页,可以看到暴露的端口。

通过 {Node IP}:{NodePort} 访问此应用程序(三台机器的任意IP都可以),可以看到下图:

6.5DevOps
项目开发需要考虑的维度
Dev:怎么开发?
Ops:怎么运维?
高并发:怎么承担高并发
高可用:怎么做到高可用
DevOps


微服务,服务自治。
DevOps: Development 和 Operations 的组合
- DevOps 看作开发(软件工程)、技术运营和质量保障(QA)三者的交集。
- 突出重视软件开发人员和运维人员的沟通合作,通过自动化流程来使得软件构建、测试、 发布更加快捷、频繁和可靠。
- DevOps 希望做到的是软件产品交付过程中 IT 工具链的打通,使得各个团队减少时间损 耗,更加高效地协同工作。专家们总结出了下面这个 DevOps 能力图,良好的闭环可以大大 增加整体的产出。
CI&CD
持续集成(Continuous Integration)
- 持续集成是指软件个人研发的部分向软件整体部分交付,频繁进行集成以便更快地发现 其中的错误。“持续集成”源自于极限编程(XP),是 XP 最初的 12 种实践之一。
- CI 需要具备这些:
- 全面的自动化测试。这是实践持续集成&持续部署的基础,同时,选择合适的 自动化测试工具也极其重要;
- 灵活的基础设施。容器,虚拟机的存在让开发人员和 QA 人员不必再大费周 折;
- 版本控制工具。如 Git,CVS,SVN 等;
- 自动化的构建和软件发布流程的工具,如 Jenkins,flow.ci;
- 反馈机制。如构建/测试的失败,可以快速地反馈到相关负责人,以尽快解决 达到一个更稳定的版本。
持续交付(Continuous Delivery)
持续交付在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境的「类生产环境」 (production-like environments)中。持续交付优先于整个产品生命周期的软件部署,建立 在高水平自动化持续集成之上。
灰度发布。
持续交付和持续集成的优点非常相似:
- 快速发布。能够应对业务需求,并更快地实现软件价值。
- 编码->测试->上线->交付的频繁迭代周期缩短,同时获得迅速反馈;
- 高质量的软件发布标准。整个交付过程标准化、可重复、可靠;
- 整个交付过程进度可视化,方便团队人员了解项目成熟度;
- 更先进的团队协作方式。从需求分析、产品的用户体验到交互 设计、开发、测试、运 维等角色密切协作,相比于传统的瀑布式软件团队,更少浪费。
持续部署(Continuous Deployment)
持续部署是指当交付的代码通过评审之后,自动部署到生产环境中。持续部署是持续交付的 最高阶段。这意味着,所有通过了一系列的自动化测试的改动都将自动部署到生产环境。它 也可以被称为“Continuous Release”。
“开发人员提交代码,持续集成服务器获取代码,执行单元测试,根据测 试结果决定是否部署到预演环境,如果成功部署到预演环境,进行整体 验收测试,如果测试通过,自动部署到产品环境,全程自动化高效运转。”
持续部署主要好处是,可以相对独立地部署新的功能,并能快速地收集真实用户的反馈。
“You build it, you run it”,这是 Amazon 一年可以完成 5000 万次部署, 平均每个工程师每天部署超过 50 次的核心秘籍。
下图是由 Jams Bowman 绘制的持续交付工具链图

落地方案
Maven+Github+Jenkins(Hudson[现由甲骨文维护])+Docker

将 SonarQube 集成到流水线
安装 SonarQube 服务器

安装Helm
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
查看 Helm 版本,我这里之前已经安装了
helm version

安装 SonarQube 服务器
helm upgrade --install sonarqube sonarqube --repo https://charts.kubesphere.io/main -n kubesphere-devops-system --create-namespace --set service.type=NodePort
获取 SonarQube 控制台地址
运行以下命令获取 NodePort 和节点的 IP 地址
export NODE_PORT=$(kubectl get --namespace kubesphere-devops-system -o jsonpath="{.spec.ports[0].nodePort}" services sonarqube-sonarqube)
export NODE_IP=$(kubectl get nodes --namespace kubesphere-devops-system -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT

配置 SonarQube 服务器
步骤 1:访问 SonarQube 控制台
访问 SonarQube 控制台,查看sonarqube-sonarqube-5487d49d79-wvpv8状态Running 才能访问控制台
kubectl get pod -n kubesphere-devops-system

在浏览器中访问 SonarQube 控制台 http://{$Node IP}:{$NodePort}
然后使用默认帐户 admin/admin 登录

步骤 2:创建 SonarQube 管理员令牌 (Token)
点击右上角字母 A,然后从菜单中选择 My Account 以转到 Profile 页面。

点击 Security 并输入令牌名称,例如 peng-mall-analyze。
点击 Generate 并复制此令牌。
如提示所示,您无法再次查看此令牌,因此请确保复制成功。
# kubesphere
b36a45e8c313beb1c99b9924082deed039bf1861

步骤 3:创建 Webhook 服务器
执行以下命令获取 SonarQube Webhook 的地址。
export NODE_PORT=$(kubectl get --namespace kubesphere-devops-system -o jsonpath="{.spec.ports[0].nodePort}" services ks-jenkins)
export NODE_IP=$(kubectl get nodes --namespace kubesphere-devops-system -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT/sonarqube-webhook/

依次点击 Administration、Configuration 和 Webhooks 创建一个 Webhook。

点击 Create。
在弹出对话框中输入 Name 和 Jenkins Console URL(即 SonarQube Webhook 地址)。点击 Create 完成操作。
ks-jenkins
http://192.168.188.181:30180/sonarqube-webhook/

步骤 4:将 SonarQube 配置添加到 ks-installer
执行以下命令编辑 ks-installer。
kubectl edit cc -n kubesphere-system ks-installer
搜寻至 devops。添加字段 sonarqube 并在其下方指定 externalSonarUrl 和 externalSonarToken。
devops:
enabled: true
jenkinsJavaOpts_MaxRAM: 2g
jenkinsJavaOpts_Xms: 512m
jenkinsJavaOpts_Xmx: 512m
jenkinsMemoryLim: 2Gi
jenkinsMemoryReq: 1500Mi
jenkinsVolumeSize: 8Gi
sonarqube: # Add this field manually.
externalSonarUrl: http://192.168.188.181:32467 # The SonarQube IP address.
externalSonarToken: b36a45e8c313beb1c99b9924082deed039bf1861 # The SonarQube admin token created above.

步骤 5:将 SonarQube 服务器添加至 Jenkins
执行以下命令获取 Jenkins 的地址
export NODE_PORT=$(kubectl get --namespace kubesphere-devops-system -o jsonpath="{.spec.ports[0].nodePort}" services ks-jenkins)
export NODE_IP=$(kubectl get nodes --namespace kubesphere-devops-system -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT

请使用地址 http://{$Public IP}:30180 访问 Jenkins。安装 KubeSphere 时,默认情况下也会安装 Jenkins 仪表板。此外,Jenkins 还配置有 KubeSphere LDAP,这意味着您可以直接使用 KubeSphere 帐户(例如 admin/P@88w0rd)登录 Jenkins。

点击左侧的系统管理。

点击系统配置

搜寻到 SonarQube servers,然后点击 Add SonarQube。

输入 Name 和 Server URL (http://{$Node IP}:{$NodePort})。点击添加,选择 Jenkins,然后在弹出对话框中用 SonarQube 管理员令牌创建凭证(如下方第二张截图所示)。创建凭证后,从 Server authentication token 旁边的下拉列表中选择该凭证。点击应用完成操作。
我这里添加按钮无效,可以使用下面方法添加凭据

如果点击添加按钮无效(Jenkins 已知问题),您可以前往系统管理下的 Manage Credentials 并点击 Stores scoped to Jenkins 下的 Jenkins,再点击全局凭据 (unrestricted),然后点击左侧导航栏的添加凭据,参考上方第二张截图用 SonarQube 管理员令牌添加凭证。添加凭证后,从 Server authentication token 旁边的下拉列表中选择该凭证。
前往系统管理下的 Manage Credentials

点击 Stores scoped to Jenkins 下的 Jenkins

再点击全局凭据 (unrestricted)

然后点击左侧导航栏的添加凭据

添加凭证
sonarqube

添加凭证后,从 Server authentication token 旁边的下拉列表中选择该凭证。

步骤 6:将 sonarqubeURL 添加到 KubeSphere 控制台
执行以下命令
kubectl edit cm -n kubesphere-system ks-console-config
搜寻到 client,添加 devops 字段并指定 sonarqubeURL
client:
version:
kubesphere: v3.1.1
kubernetes: v1.18.0
openpitrix: v0.3.5
enableKubeConfig: true
devops: # Add this field manually.
sonarqubeURL: http://192.168.188.181:32467/ # The SonarQube IP address.

步骤 7:重启服务
kubectl -n kubesphere-system rollout restart deploy ks-apiserver
kubectl -n kubesphere-system rollout restart deploy ks-console

6.6流水线-创建凭证

步骤 1:创建凭证
使用project-admin登录,创建凭证
凭证 ID 类型 用途
dockerhub-id 帐户凭证 Docker Hub
github-id 帐户凭证 GitHub
demo-kubeconfig kubeconfig Kubernetes

为 SonarQube 创建一个凭证 ID (sonar-token),用于上述的阶段 3(SonarQube 分析)。
sonar-token
b36a45e8c313beb1c99b9924082deed039bf1861
SonarQube

您还需要创建具有如下图所示权限的 GitHub 个人访问令牌 (PAT),然后在 DevOps 项目中,使用生成的令牌创建用于 GitHub 认证的帐户凭证(例如,github-token)。
如需创建 GitHub 个人访问令牌,请转到您 GitHub 帐户的 Settings,点击 Developer settings,选择 Personal access tokens,然后点击 Generate new token。

创建具有如下图所示权限的 GitHub 个人访问令牌 (PAT),然后在 DevOps 项目中,使用生成的令牌创建用于 GitHub 认证的帐户凭证(例如,github-token)。

在列表中看到已创建的五个凭证。

步骤 2:在 GitHub 仓库中修改 Jenkinsfile
登录 GitHub 并 Fork GitHub 仓库 devops-java-sample 至您的 GitHub 个人帐户

点击Create fork,取消Copy the master branch only,复制所有分支

在您自己的 GitHub 仓库 devops-java-sample 中,选择sonarqube分支,点击根目录中的文件 Jenkinsfile-online。

点击右侧的编辑图标,编辑环境变量。
environment {
DOCKER_CREDENTIAL_ID = 'dockerhub-id'
GITHUB_CREDENTIAL_ID = 'github-id'
KUBECONFIG_CREDENTIAL_ID = 'peng-mall-kubeconfig'
REGISTRY = 'docker.io'
DOCKERHUB_NAMESPACE = 'pengeng'
GITHUB_ACCOUNT = 'pengpeng-github'
APP_NAME = 'devops-java-sample'
SONAR_CREDENTIAL_ID = 'sonar-token'
}
添加以下凭证
条目 值 描述信息
DOCKER_CREDENTIAL_ID dockerhub-id 您在 KubeSphere 中为 Docker Hub 帐户设置的凭证 ID。
GITHUB_CREDENTIAL_ID github-id 您在 KubeSphere 中为 GitHub 帐户设置的凭证 ID,用于将标签推送至您的 GitHub 仓库。
KUBECONFIG_CREDENTIAL_ID demo-kubeconfig 您在 KubeSphere 中为 kubeconfig 设置的凭证 ID,用于访问运行中的 Kubernetes 集群。
REGISTRY docker.io 默认为 docker.io,用作推送镜像的地址。
DOCKERHUB_NAMESPACE your-dockerhub-account 请替换为您的 Docker Hub 帐户名,也可以替换为该帐户下的 Organization 名称。
GITHUB_ACCOUNT your-github-account 请替换为您的 GitHub 帐户名。例如,如果您的 GitHub 地址是 https://github.com/kubesphere/,则您的 GitHub 帐户名为 kubesphere,也可以替换为该帐户下的 Organization 名称。
APP_NAME devops-java-sample 应用名称。
SONAR_CREDENTIAL_ID sonar-token 您在 KubeSphere 中为 SonarQube 令牌设置的凭证 ID,用于代码质量检测。


Jenkinsfile 中
mvn命令的参数-o表示开启离线模式。本教程中已下载相关依赖项,以节省时间并适应某些环境中的网络干扰。离线模式默认开启。
步骤 3:创建项目
以 project-admin 身份登录 KubeSphere。在您创建 DevOps 工程的企业空间中创建以下两个项目。
项目名称 别名
kubesphere-sample-dev development environment
kubesphere-sample-prod production environment

请确保邀请 project-regular 帐户至这两个项目中并赋予 operator 角色。
kubesphere-sample-prod

kubesphere-sample-dev

6.7流水线-CICD完整体验
KubeSphere服务创建内网穿透
配置KubeSphere服务内网穿透的ip和端口

使用内网穿透地址访问KubeSphere服务,这样webhook的消息可以正常推送了

步骤 4:创建流水线
创建构建新流水线
配置流水线名称和选择一个代码仓库。

在 GitHub 选项卡,从下拉菜单中选择 github-token,然后点击确认来选择您的仓库

选择您的 GitHub 帐户,与该令牌相关的所有仓库将在右侧列出。选择 devops-java-sample 并点击选择此仓库,点击下一步继续。

在高级设置中,选中丢弃旧的分支旁边的方框。本教程中,您可以为保留分支的天数和保留分支的最大个数使用默认值。
KubeSphere 默认用 -1 预填充这两个字段,表示已删除的分支将被丢弃。

在行为策略中,KubeSphere 默认提供四种策略。本示例中不会使用从 Fork 仓库中发现 PR 这条策略,因此您可以删除该策略。您无需修改设置,可以直接使用默认值。

向下滚动到脚本路径。该字段指定代码仓库中的 Jenkinsfile 路径。它表示仓库的根目录。如果文件位置变更,则脚本路径也需要更改。请将其更改为 Jenkinsfile-online,这是示例仓库中位于根目录下的 Jenkinsfile 的文件名。

配置webhock

步骤 5:运行流水线
流水线创建后,将显示在下图所示的列表中。点击该流水线进入其详情页面。

devops-java-sample有几个分支这里就有几个

在活动选项卡下,正在扫描三个分支。点击右侧的运行,流水线将根据您设置的行为策略来运行。从下拉列表中选择 sonarqube,然后添加标签号,例如 v0.0.2。点击确定触发新活动。

创作不易,感谢支持。


浙公网安备 33010602011771号