• [技术干货] 爆肝整理的最新版的K8S安装教程,看完还不会,请你吃瓜
    > 最近在参加华为推出的[华为云云原生入门级开发者认证人才计划活动](https://edu.huaweicloud.com/signup/521bd9a32c9345d5b240d4173e67437a) 于是想自己动手部署K8S的环境来学习,去年自己也采用二进制的方式部署过,时隔一年K8S的版本已经更新到了v1.24.3啦。在v1.24版本之后,k8s都已经抛弃了docker。抱着学习的心态尝试了k8s的v1.24.3版本的安装,这次采用kubeadm的部署方式,过程非常坎坷,但是还是顺利的部署成功。 # 环境准备 三台机都是采用centos7的操作系统,内核版本号是`3.10.0-693.el7.x86_64` ------------ | 角色 | IP | kubernetes版本 | | --- | --- | --- | | master | 192.168.248.130 | v1.24.3 | | node1 | 192.168.248.131 | v1.24.3 | | node2 | 192.168.248.132 | v1.24.3 | ------------ >由于K8S从1.24版本之后,开始弃用了docker。改用了containerd ,containerd是容器虚拟化技术,从docker中剥离出来,形成开放容器接口(OCI)标准的一部分。 containerd与docker相兼容,相比docker轻量很多,目前较为成熟。 ## 主机间做信任 在master节点上生成秘钥文件,并把它上传到其他两台机上,做好免密登录,方便后续的操作。 ![](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/29/1659065562359970114.png) 执行`ssh-copy-id root@192.168.248.129`命令实现免密登录,其他两台做同样的操作。 ## 安装ansible工具 `ansible`工具主要为了后续多台机器执行同样的命令,从而提供效率用的。安装方式也很简单,通过yum源安装即可。执行如下两条命令: ```shell [root@master ~]# yum install epel-release -y [root@master ~]# yum -y install ansible ``` 配置`/etc/ansible/hosts`,该文件是存放要操作的主机,把上述三台机器加入一个组名字为`k8s`,如下: ```shell [k8s] 192.168.248.128 192.168.248.129 192.168.248.130 ``` 通过执行ansible命令测试连通性,如下图: ![](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/29/1659065635022984293.png) > -m:是指定ansible的模块,ping是ansible其中一个模块,该模块主要是测试主机的连通性。 > k8s:刚定义的组名 # 升级内核版本 检查当前 `CentOS `系统内核版本 ,执行如下命令查看: ```shell [root@localhost ~]# uname -sr Linux 3.10.0-1160.el7.x86_64 ``` 检查发现当前内核版本是3.10, ## 使用elrepo源升级内核 配置elrepo源,执行如下命令 ```powershell rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org yum install https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm ``` ## 查看最新版内核 执行如下命令查看最新的内核版本 ```shell yum --disablerepo="*" --enablerepo="elrepo-kernel" list available ``` ![](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/29/1659065712911474445.png) > 内核版本说明: > - kernel-ml #主线版本,比较新 > - kernel-lt #长期支持版本,比较旧 ## 安装最新的内核版本 执行如下命令安装主线版本: ```shell yum --enablerepo=elrepo-kernel install kernel-ml -y ``` ## 设置系统默认内核 查看系统上的所有内核版本: ```shell [root@localhost ~]# awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg 0 : CentOS Linux (5.18.14-1.el7.elrepo.x86_64) 7 (Core) 1 : CentOS Linux (3.10.0-1160.el7.x86_64) 7 (Core) 2 : CentOS Linux (0-rescue-9dad18ee9dde4729b1c6df225ce69c4a) 7 (Core) [root@localhost ~]# ``` 设置默认内核为我们刚才升级的内核版本 ```shell cp /etc/default/grub /etc/default/grub-bak #备份 grub2-set-default 0 #设置默认内核版本 vi /etc/default/grub GRUB_DEFAULT=saved修改为GRUB_DEFAULT=0 ``` 重新创建内核配置 ```shell grub2-mkconfig -o /boot/grub2/grub.cfg ``` 查看默认内核 ```shell grubby --default-kernel #/boot/vmlinuz-5.18.14-1.el7.elrepo.x86_64 grub2-editenv list #saved_entry=0 ``` 更新软件包并重启 ```shell yum makecache reboot ``` # 初始化 安装K8S之前需要对系统进行一些设置,比如 关闭防火墙,selinux,swap,设置主机名,ip解析,时间同步 。 ## 关闭防火墙 通过`ansible`把三台机器的防火墙关闭,并设置开机不启动。执行如命令: ```shell ansible k8s -m shell -a "systemctl stop firewalld" ansible k8s -m shell -a "systemctl disable firewalld " ``` ![](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/29/1659065765643641740.png) ## 关闭selinux 通过`ansible`把三台机器的selinux永久关闭,执行如命令: ```shell ansible k8s -m shell -a "sed -i 's/enforcing/disabled/' /etc/selinux/config" ``` ![](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/29/1659065806500972533.png) ## 关闭swap 执行`swapoff -a` 临时关闭,通过修改/etc/fstab文件实现永久关闭。执行如下命令 ```shell ansible k8s -m shell -a "sed -ri 's/.*swap.*/#&/' /etc/fstab" ``` ![](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/29/1659065830661597284.png) ## 修改主机名 分别对三台主机进行主机名的修改,执行如下的命令 ```shell # 根据规划设置主机名【master节点上操作】 hostnamectl set-hostname master # 根据规划设置主机名【node1节点操作】 hostnamectl set-hostname node1 # 根据规划设置主机名【node2节点操作】 hostnamectl set-hostname node2 ``` ## 修改hosts文件 在master节点上修改hosts文件,根据规划进行修改,如下: ``` 192.168.248.130 master1 192.168.248.131 node2 192.168.248.132 node1 ``` ## 将桥接的IPv4流量传递到iptables的链 在`/etc/sysctl.d/`目录上新增`k8s.conf`,内容如下,并把该文件拷贝到其他两台机器上 ``` net.bridge.bridge-nf-call-ip6tables = 11 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 ``` ```shell ansible k8s -m copy -a "src=/etc/sysctl.d/k8s.conf dest=/etc/sysctl.d/k8s.conf" ``` ![](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/29/1659065860430811290.png) 执行 `sysctl --system`命令使配置生效: ```shell ansible k8s -m shell -a "sysctl --system" ``` ## 配置时间同步 使用yum命令安装`ntpdate `,如下: ```shell ansible k8s -m shell -a "yum install ntpdate -y" ``` 配置NTP网络时间同步服务器地址为 `ntp.aliyun.com`,执行如下命令: ```shell ansible k8s -m shell -a "ntpdate ntp.aliyun.com" ``` # 安装containerd 执行如下命令下载最新containerd,如下: ```shell wget https://download.fastgit.org/containerd/containerd/releases/download/v1.6.6/cri-containerd-cni-1.6.6-linux-amd64.tar.gz ``` > 如果出现无法建立 SSL 连接 加上--no-check-certificate 解压`containerd`安装包 ```shell tar -C / -zxf cri-containerd-cni-1.6.6-linux-amd64.tar.gz ``` 配置环境变量,编辑用户目录下的`bashrc`文件添加如下内容: ```shell export PATH=$PATH:/usr/local/bin:/usr/local/sbin ``` 并执行如下命令使环境变量立即生效: ```shell source ~/.bashrc ``` 执行如下命令启动`containerd` ```shell systemctl start containerd ``` 执行如下命令查看版本号,出现如下信息表明安装成功。 ```shell [root@master1 ~]# ctr version Client: Version: v1.6.6 Revision: 10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1 Go version: go1.17.11 Server: Version: v1.6.6 Revision: 10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1 UUID: c205638a-6c08-43a8-81a4-b15f97ef5cdc ``` 创建默认配置文件 ```shell mkdir /etc/containerd containerd config default > /etc/containerd/config.toml ``` ## 测试containerd是否能创建和启动成功 执行如下命令拉取镜像并创建容器: ```shell ctr i pull docker.io/library/nginx:alpine #拉取容器 ctr c create --net-host docker.io/library/nginx:alpine nginx #创建容器 ctr task start -d nginx ``` 如果启动容器出现如下报错,是由于 缺少 `runc`并升级`libseccomp`,`libseccomp`需要高于`2.4`版本。 > `containerd`在`v1.6.4`版本以后使用`v1.1.2`的`runc`和`v1.1.1`的`cni`。 ```json ctr: failed to create shim task: OCI runtime create failed: unable to retrieve OCI runtime error (open /run/containerd/io.containerd.runtime.v2.task/default/nginx/log.json: no such file or directory): fork/exec / ``` [下载链接](https://github.com/opencontainers/runc/releases/download/v1.1.2/runc.amd64),下载之后,执行如下命令安装并查看版本号: ```shell install -m 755 runc.amd64 /usr/local/sbin/runc runc -v ``` 执行如下命令升级`libseccomp`: ```shell rpm -qa | grep libseccomp #查询原来的版本 rpm -e libseccomp-2.3.1-4.el7.x86_64 --nodeps #卸载原来的版本 #下载高版本的 wget http://rpmfind.net/linux/centos/8-stream/BaseOS/x86_64/os/Packages/libseccomp-2.5.1-1.el8.x86_64.rpm rpm -ivh libseccomp-2.5.1-1.el8.x86_64.rpm #安装 ``` # 安装kubernetes ## 添加kubernetes源 在master节点上添加k8s软件源,并分发到其他两台机器上。在`/etc/yum.repos.d/`目录下新增`kubernetes.repo`。内容如下: ```latex [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 ``` 把kubernetes.repo文件分发到其他两台机器上,执行如下命令: ```shell ansible k8s -m copy -a "src=/etc/yum.repos.d/kubernetes.repo dest=/etc/yum.repos.d/kubernetes.repo" ``` ![](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/29/1659065897405991036.png) ## 安装 在master节点下执行如下命令安装相应的软件: ```shell yum install -y kubelet-1.24.3 kubeadm-1.24.3 kubectl-1.24.3 ``` ## 生成默认配置并修改相应的参数 通过如下命名生成一个默认的配置文件: ```powershell kubeadm config print init-defaults > kubeadm-init.yaml ``` 根据自己的环境修改对应的参数: ```yaml apiVersion: kubeadm.k8s.io/v1beta3 bootstrapTokens: - groups: - system:bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s usages: - signing - authentication kind: InitConfiguration localAPIEndpoint: advertiseAddress: 192.168.248.130 #master节点IP bindPort: 6443 nodeRegistration: criSocket: unix:///run/containerd/containerd.sock #containerd容器路径 imagePullPolicy: IfNotPresent name: master1 taints: null --- apiServer: timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta3 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controllerManager: {} dns: {} etcd: local: dataDir: /var/lib/etcd imageRepository: registry.aliyuncs.com/google_containers #阿里云容器源地址 kind: ClusterConfiguration kubernetesVersion: 1.24.3 networking: dnsDomain: cluster.local podSubnet: 10.244.0.0/16 #pod的IP网段 serviceSubnet: 10.96.0.0/12 scheduler: {} ``` ## 初始化 执行如下命令进行初始化: ```shell kubeadm init --config=kubeadm-init.yaml --v=6 ``` > --config:指定根据那个配置文件进行初始 > --v:指定日志级别,越高越详细 初始化成功后,会出现以下信息 ```shell ...省略... Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config Alternatively, if you are the root user, you can run: export KUBECONFIG=/etc/kubernetes/admin.conf You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/ Then you can join any number of worker nodes by running the following on each as root: kubeadm join 192.168.248.130:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:e9e29c804f92193928f37ca157b73a7ad77e7929314db98855b3ba6e2ce2273d ``` 按照初始化成功提示信息,做如下操作: ```shell mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config ``` 接下来执行`kubectl`就可以看到`node`了 ```shell [root@master1 .kube]# kubectl get node NAME STATUS ROLES AGE VERSION master1 Ready control-plane 55m v1.24.3 ``` 查看k8s各部件启动情况,执行如下命令: ```shell kubectl get pod --all-namespaces -o wide ``` ![](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/29/1659065927835960442.png) 通过观察发现`coredns`部件没有运行成功,通过如下命令查看原因: ```shell describe pod coredns-74586cf9b6-c2ddb --namespace=kube-system ``` ![](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/29/1659065970164571642.png) > 根据官方的解析是没有部署CNI,coredns是不会启动的。 ![](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/29/1659066136690220591.png) ## node节点配置 node节点安装kubeadm ```shell cat /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 ``` 安装相关组件 ```shell yum install -y kubeadm-1.24.3 --disableexcludes=kubernetes ``` 添加join命令 ```powershell kubeadm join 192.168.248.130:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:e9e29c804f92193928f37ca157b73a7ad77e7929314db98855b3ba6e2ce2273d ``` 如果我们后续需要添加node节点时,可以到master节点执行下面的命令获取`token`相关信息 ```shell [root@master1 ~]# kubeadm token create --print-join-command kubeadm join 192.168.248.130:6443 --token ydqnz1.6b0q5ntkvos9z2ir --discovery-token-ca-cert-hash sha256:c0b6f7fb38c7c9764084beb7dd26c9acef027ae6b7d2673572b4c2e3a0dfd6cb ``` > 如果添加某台节点异常了,修改后可以执行 `kubeadm reset `的命令,然后在重新join加入 ## 网络配置 coredns还没启动,因为还没有安装网络插件,接下来安装网络插件,可以在[该文档中](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/)选择我们自己的网络插件,这里安装`flannel` ```shell wget http://down.i4t.com/k8s1.24/kube-flannel.yml ``` 根据需求修改网卡配置,我这里ens33为主的: ```yaml containers: - name: kube-flannel image: quay.io/coreos/flannel:v0.12.0-amd64 command: - /opt/bin/flanneld args: - --ip-masq - --kube-subnet-mgr - --iface=ens33 # 如果是多网卡的话,指定内网网卡的名称 ``` > 在kubeadm.yaml文件中设置了podSubnet网段,同时在flannel中网段也要设置相同的。 (我这里默认就是相同的配置) 执行部署 ```shell kubectl apply -f kube-flannel.yml ``` ## CNI插件问题 默认情况下containerd也会有一个cni插件,但是我们已经安装Flannel了,我们需要使用Flannel的cni插件,需要将containerd里面的cni配置文件进行注释,否则2个配置会产生冲突 。 因为如果这个目录中有多个 cni 配置文件,kubelet 将会使用按文件名的字典顺序排列的第一个作为配置文件,所以前面默认选择使用的是 containerd-net 这个插件。 ```shell mv /etc/cni/net.d/10-containerd-net.conflist /etc/cni/net.d/10-containerd-net.conflist.bak systemctl restart containerd kubelet ``` 接下来我们所有的pod都可以正常运行了 ![](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/29/1659066190540760518.png) # 验证 验证dns是否正常能解析和pod之间。这里新建一个测试的yaml文件,内容如下: ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx:alpine name: nginx ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx spec: selector: app: nginx type: NodePort ports: - protocol: TCP port: 80 targetPort: 80 nodePort: 30001 --- apiVersion: v1 kind: Pod metadata: name: busybox namespace: default spec: containers: - name: busybox image: abcdocker9/centos:v1 command: - sleep - "3600" imagePullPolicy: IfNotPresent restartPolicy: Always ``` 执行下面命令,创建pod ```shell kubectl apply -f test.yaml ``` ![](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/29/1659066222393991839.png) 使用nslookup查看是否能返回地址 ```shell [root@master1 ~]# kubectl exec -it busybox -- nslookup kubernetes Server: 10.96.0.10 Address: 10.96.0.10#53 Name: kubernetes.default.svc.cluster.local Address: 10.96.0.1 [root@master1 ~]# ``` 测试nginx svc以及Pod内部网络通信是否正常 ,分别在三台机器上进行下面操作 ```powershell ping 10.104.115.26 #nginx svc ip ping 10.244.1.2 #podIP ``` 如果成功ping同说明node跟pod的网络已经打通了。否则检查`kube-proxy`的模式是否正确。 ## nodes/集群内部 无法访问ClusterIP 默认情况下,我们部署的`kube-proxy`通过查看日志,能看到如下信息:`Flag proxy-mode="" unknown,assuming iptables proxy ` **原因分析:** 并没有正确使用ipvs模式 解决方法: 1、 在`master`上修改`kube-proxy`的配置文件,添加`mode `为`ipvs`。 ```shell [root@master1 ~]# kubectl edit cm kube-proxy -n kube-system ipvs: excludeCIDRs: null minSyncPeriod: 0s scheduler: "" strictARP: false syncPeriod: 30s kind: KubeProxyConfiguration metricsBindAddress: 127.0.0.1:10249 mode: "ipvs" ``` 删除原来的POD,会自动重启kube-proxy 的pod ```shell [root@k8s-master ~]# kubectl get pod -n kube-system | grep kube-proxy |awk '{system("kubectl delete pod "$1" -n kube-system")}' ``` # 扩展 在使用过程中发现kubectl 命令不能补全,使用起来很不方便。为了提高使用kubectl命令工具的便捷性,介绍一下kubectl命令补全工具的安装。 1、安装bash-completion: ```shell yum install -y bash-completion source /usr/share/bash-completion/bash_completion ``` 2、 应用kubectl的completion到系统环境: ```shell source (kubectl completion bash) echo "source (kubectl completion bash)" >> ~/.bashrc ``` 3、效果展示 ![](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/29/1659066247701546584.png)
  • [沙箱纠错] 基于CCE Kubernetes编排实战_步骤
    创建kubenetes用户节点报错,如何解决?
  • [沙箱纠错] 基于CCE Kubernetes编排实战
    权限不足应该怎么解决 大佬们帮帮孩子吧
  • [大咖交流] 视频存储容器化
    一.存储容器化存储作为基础组件,直接和本地盘打交道,所以我们一个要解决的事情就是如果Kubernetes 管理本地盘。kubernetes管理本地盘通过官方提供的local-static-provisioner自动生成LocalPersistentVolume管理磁盘。LocalPersistentVolume是Kubernetes提供的一种管理本地盘的资源。5.1 使用Statefulset管理存储容器通过statefulset 管理有状态的存储服务, 为每个pod分配一个单独的磁盘可以使用volumeClaimTemplates给每个pod生成唯一的pvc,具体规则{podName},事先准备好PVC 和 PV,通过Statefulset 我们就可以把我们的存储托管到云上了。另外借助daemonset,可以把我们gateway模块部署到每一个node上面。处理云存储的请求。5.2 存储容器化的收益1)降低运维成本基于Kubernetes和statfulset获得了滚动更新,灰度更新,健康检查,快速扩容等功能,只需要一组yaml文件就可以快速搭建一个集群,相比于传统写ansible脚本部署的方式复杂度大大降低。2)降低开发运维成本由于Kubernetes把存储抽象成StorageClass PersistentVolume PersistentVolumeClaim。我们可以通过他们管理我们的存储资源,基于Kubernetes lable的过滤功能,可以实现简单的关系查询,通过PVC与PV管理存储资源,减少管理端的开发。定位问题也能通过POD信息快速定位到问题机器和问题云盘。而且接入Kubernetes生态上的prometheus后,监控告警也能快速开发。3)隔离性增强docker限制cpu memory使用,减少进程之间资源互相干扰,进一步提升资源利用率。在做流媒体容器化过程中,各个系统 Portal 平台、中间件、ops 基础设施、监控等都做了相应的适配改造,改造后的架构矩阵如下图所示。1. Portal:流媒体 的 PaaS 平台入口,提供 CI/CD 能力、资源管理、自助运维、应用画像、应用授权(db 授权、支付授权、应用间授权)等功能。2.运维工具:提供应用的可观测性工具, 包括 watcher(监控和报警)、bistoury (Java 应用在线 Debug)、qtrace(tracing 系统)、loki/elk(提供实时日志/离线日志查看)。中间件:应用用到的所有中间件,mq、配置中心、分布式调度系统 qschedule、dubbo 、mysql sdk 等。3.虚拟化集群:底层的 K8s 和 OpenStack 集群。4.Noah:测试环境管理平台,支持应用 KVM/容器混合部署。一.CI/CD 流程改造主要改造点:应用画像: 把应用相关的运行时配置、白名单配置、发布参数等收敛到一起,为容器发布提供统一的声明式配置。授权系统: 应用所有的授权操作都通过一个入口进行,并实现自动化的授权。K8s 多集群方案: 通过调研对比,KubeSphere 对运维优化、压测评估后也满足我们对性能的要求,最终我们选取了 KubeSphere 作为多集群方案。二.中间件适配改造改造关注点:由于容器化后,IP 经常变化是常态,所以各个公共组件和中间件要适配和接受这种变化。Qmq组件改造点:Broker端加快过期数据的处理速度。原因:由于IP变化频繁,对于一个主题有几百个甚至上千个的IP订阅,会产生很多文件Qconfig/Qschedule组件改造点:按实例级别的推送、任务执行在容器场景下不建议使用 。原因:因为IP经常变化,在容器化场景下发布、pod驱逐等都会导致IP变化,按实例维度推送没有意义Dubbo组件改造点:更改上线下线逻辑,下线记录由永久节点改为临时节点。 原因:上下线机制加上频繁的IP变更会导致zookeeper上产生大量的过期数据Openresty改造点:监听多K8s集群的endpoint变更,并更新到upstream; KVM、容器server地址共存,支持KVM和容器混合部署;三应用平滑迁移方案设计为了帮助业务快速平滑地迁移到容器,制定了一些规范和自动化测试验证等操作来实现这个目标。1.容器化的前置条件: 应用无状态、不存在 post_offline hook(服务下线后执行的脚本)、check_url 中不存在预热操作。2.测试环境验证: 自动升级 SDK、自动迁移。我们会在编译阶段帮助业务自动升级和更改 pom 文件来完成 SDK 的升级,并在测试环境部署和验证,如果升级失败会通知用户并提示。3.线上验证: 第一步线上发布,但不接线上流量,然后通过自动化测试验证,验证通过后接入线上流量。4.线上 KVM 与容器混部署:保险起见,线上的容器和 KVM 会同时在线一段时间,等验证期过后再逐步下线 KVM。5.线上全量发布: 确认服务没问题后,下线 KVM。6.观察: 观察一段时间,如果没有问题则回收 KVM。
  • [知识分享] 使用Karmada实现Helm应用的跨集群部署
    【摘要】 Karmada已经实现了多集群场景下的Kubernetes资源(包括CRD)的分发以及管理。但当前多集群应用往往不是单一的资源形式,使用Helm对应用进行打包的使用场景也非常常见。借助Karmada原生API的支持能力,Karmada可以借助Flux轻松实现Helm应用的跨集群部署。本文分享自华为云社区《 使用Karmada实现Helm应用的跨集群部署【云原生开源】》,作者:华为云云原生开源团队。背景通过使用 Kubernetes 原生 API 并提供高级调度功能,Karmada已经实现了多集群场景下的Kubernetes资源(包括CRD)的分发以及管理。但当前多集群应用往往不是单一的资源形式,使用Helm对应用进行打包的使用场景也非常常见。借助Karmada原生API的支持能力,Karmada可以借助Flux轻松实现Helm应用的跨集群部署。部署Karmada要部署Karmada,你可以参考社区的安装文档(https://github.com/karmada-io/karmada/blob/master/docs/installation/installation.md)。如果想快速体验Karmada,我们建议通过hack/local-up-karmada.sh构建一个Karmada的开发环境。部署Flux在Karmada控制面中,你需要安装Flux的CRD,但不需要安装Flux控制器来调和基于CRD创建的CR对象,它们被视为资源模板,而不是特定的资源实例。基于Karmada的work API,它们将被封装为一个work对象下发给成员集群,最终由成员集群中的Flux控制器进行调和。kubectl apply -k github.com/fluxcd/flux2/manifests/crds?ref=main --kubeconfig ~/.kube/karmada.config在成员集群中,你可以基于以下命令安装完整的Flux组件。flux install --kubeconfig ~/.kube/members.config --context member1 flux install --kubeconfig ~/.kube/members.config --context member2你可以参考此处的文档(https://fluxcd.io/docs/installation/)来获得更详细的安装Flux的细节。提示:如果你想在你所有的集群上管理基于HelmRelease的应用,你需要在你的所有成员集群中安装Flux。Helm release分发准备工作就绪,下面将以一个podinfo的简单应用为例演示如何完成Helm chart分发。1.在 Karmada 控制平面中定义一个 Flux 的HelmRepository CR对象和一个 HelmRelease CR对象。它们将视作资源模板。apiVersion: source.toolkit.fluxcd.io/v1beta2 kind: HelmRepository metadata: name: podinfo spec: interval: 1m url: https://stefanprodan.github.io/podinfo---apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease metadata: name: podinfo spec: interval: 5m chart: spec: chart: podinfo version: 5.0.3 sourceRef: kind: HelmRepository name: podinfo2. 定义一个 Karmada的PropagationPolicy 对象将它们的资源实例下发到成员集群:apiVersion: policy.karmada.io/v1alpha1 kind: PropagationPolicy metadata: name: helm-repo spec: resourceSelectors: - apiVersion: source.toolkit.fluxcd.io/v1beta2 kind: HelmRepository name: podinfo placement: clusterAffinity: clusterNames: - member1 - member2---apiVersion: policy.karmada.io/v1alpha1 kind: PropagationPolicy metadata: name: helm-release spec: resourceSelectors: - apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease name: podinfo placement: clusterAffinity: clusterNames: - member1 - member2上述配置将会把Flux的资源对象下发到成员集群member1和member2中。3. 将上述对象提交给Karmada-apiserver:kubectl apply -f ../helm/ --kubeconfig ~/.kube/karmada.config你将会得到以下的输出结果:helmrelease.helm.toolkit.fluxcd.io/podinfo created helmrepository.source.toolkit.fluxcd.io/podinfo created propagationpolicy.policy.karmada.io/helm-release created propagationpolicy.policy.karmada.io/helm-repo created4. 切换至成员集群验证应用是否成功下发helm --kubeconfig ~/.kube/members.config --kube-context member1 list你将会得到以下的输出结果:基于 Karmada 的 PropagationPolicy,你可以灵活地将 Helm应用发布到你期望的集群。为特定集群定制 Helm 应用上述的示例显示了如何将同一个Helm应用分发到 Karmada 中的多个集群。此外,你还可以使用 Karmada 的 OverridePolicy 为特定集群定制Helm应用。例如,上述应用包括了一个Pod副本,如果你只想更改 member1集群中的应用所包含的Pod副本数,你可以参考以下的 OverridePolicy策略。1.定义一个Karmada的OverridePolicy对象。apiVersion: policy.karmada.io/v1alpha1 kind: OverridePolicy metadata: name: example-override namespace: default spec: resourceSelectors: - apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease name: podinfo overrideRules: - targetCluster: clusterNames: - member1 overriders: plaintext: - path: "/spec/values" operator: add value: replicaCount: 22. 将上述对象提交给Karmada-apiserver:kubectl apply -f example-override.yaml --kubeconfig ~/.kube/karmada.config你将会得到以下的输出结果:overridepolicy.policy.karmada.io/example-override created3. 在 Karmada 控制平面中应用上述策略后,你会发现 member1成员集群中的Pod实例数已变更为 2,但 member2 集群中的那些保持不变。kubectl --kubeconfig ~/.kube/members.config --context member1 get po你将会得到以下的输出结果:NAME READY STATUS RESTARTS AGE podinfo-68979685bc-6wz6s 1/1 Running 0 6m28s podinfo-68979685bc-dz9f6 1/1 Running 0 7m42s参考文档:https://github.com/karmada-io/karmada/blob/master/docs/working-with-flux.md附:Karmada社区技术交流地址添加Karmada社区助手微信k8s2222进入社区交流群,和Maintainer零距离。项目地址https://github.com/karmada-io/karmadaSlack地址:https://slack.cncf.io/
  • [交流讨论] 换个角度看Kubernetes 的核心
    本文来自微信公共号:分布式实验室。文章观点独特,比喻形象,分享给大家~本文论述了 Kubernetes 的核心价值是其通用、跨厂商和平台、可灵活扩展的声明式 API 框架, 而不是容器(虽然容器是它成功的基础);然后手动创建一个 API Extension(CRD), 通过测试和类比来对这一论述有一个更直观的理解。例子及测试基于 Kubernetes v1.21.0。— 1 —Kubernetes 的核心是其 API 框架而非容器 容器是基础时间回到 2013 年。当一条简单的 docker run postgre 命令就能运行起 Postgre 这样复杂的传统服务时,开发者在震惊之余犹如受到天启;以 Docker 为代表的实用容器技术的横空出世,也预示着一扇通往敏捷基础设施的大门即将打开。此后,一切都在往好的方向迅速发展:越来越多的开发者开始采用容器作为一种标准构建和运行方式。业界也意识到,很容易将这种封装方式引入计算集群,通过 Kubernetes 或 Mesos 这样的编排器来调度计算任务 —— 自此,容器便成为这些调度器最重要的 Workload 类型。但本文将要说明,容器并非 Kubernetes 最重要、最有价值的地方,Kubernetes 也并非仅仅是一个更广泛意义上的 Workload 调度器 —— 高效地调度不同类型的 Workload 只是 Kubernetes 提供的一种重要价值,但并不是它成功的原因。API 才是核心“等等 —— Kubernetes 只是一堆 API?”“不好意思,一直都是!”Kubernetes 的成功和价值在于,提供了一种标准的编程接口(API),可以用来编写和使用软件定义的基础设施服务(本文所说的“基础设施”,范围要大于 IaaS):Specification + Implementation 构成一个完整的 API 框架 —— 用于设计、实现和使用各种类型和规模的基础设施服务;这些 API 都基于相同的核心结构和语义:typed resources watched and reconciled by controllers (资源按类型划分,控制器**相应类型的资源,并将其实际 status 校准到 spec 里期望的状态)。为了进一步解释这一点,考虑下 Kubernetes 出现之前的场景。Kubernetes 之前:各自造轮子,封装厂商 API 差异Kubernetes 之前,基础设施基本上是各种不同 API、格式和语义的“云”服务组成的大杂烩:云厂商只提供了计算实例、块存储、虚拟网络和对象存储等基础构建模块,开发者需要像拼图一样将它们拼出一个相对完整的基础设施方案;对于其他云厂商,重复过程 1,因为各家的 API、结构和语义并不相同,甚至差异很大。虽然 Terraform 等工具的出现,提供了一种跨厂商的通用格式,但原始的结构和语义仍然是五花八门的,—— 针对 AWS 编写的 Terraform descriptor 是无法用到 Azure 的。Kubernetes 面世:标准化、跨厂商的 API、结构和语义现在再来看 Kubernetes 从一开始就提供的东西:描述各种资源需求的标准 API。例如:描述 Pod、Container 等计算需求的 API;描述 Service、Ingress 等虚拟网络功能的 API;描述 Volumes 之类的持久存储的 API;甚至还包括 Service Account 之类的服务身份的 API 等等。这些 API 是跨公有云/私有云和各家云厂商的,各云厂商会将 Kubernetes 结构和语义对接到它们各自的原生 API。因此我们可以说,Kubernetes 提供了一种管理软件定义基础设施(也就是云)的标准接口。或者说,Kubernetes 是一个针对云服务(Cloud Services)的标准 API 框架。Kubernetes API 扩展:CRD提供一套跨厂商的标准结构和语义来声明核心基础设施(Pod/Service/Volume/ServiceAccount/……), 是 Kubernetes 成功的基础。在此基础上,它又通过 CRD(Custom Resource Definition), 将这个结构扩展到任何/所有基础设施资源。CRD 在 1.7 引入,允许云厂商和开发者自己的服务复用 Kubernetes 的 spec/impl 编程框架。有了 CRD,用户不仅能声明 Kubernetes API 预定义的计算、存储、网络服务,还能声明数据库、task runner、消息总线、数字证书……任何云厂商能想到的东西!Operator Framework 以及 SIG API Machinery 等项目的出现,提供了方便地创建和管理这些 CRD 的工具,最小化用户工作量,最大程度实现标准化。例如,Crossplane 之类的项目,将厂商资源 RDS 数据库、SQS queue 资源映射到 Kubernetes API,就像核心 Kubernetes controller 一样用自己的 controller 来管理网卡、磁盘等自定义资源。Google、RedHat 等 Kubernetes 发行商也在它们的基础 Kubernetes 发行版中包含越来越多的自定义资源类型。小结我们说 Kubernetes 的核心是其 API 框架,但并不是说这套 API 框架就是完美的。事实上,后一点并不(非常)重要,因为 Kubernetes 模型已经成为一个事实标准:开发者理解它、大量工具主动与它对接、主流厂商也都已经原生支持它。用户认可度、互操作性 经常比其他方面更能决定一个产品能否成功。随着 Kubernetes 资源模型越来越广泛的传播,现在已经能够 用一组 Kubernetes 资源来描述一整个软件定义计算环境。就像用 docker run 可以启动单个程序一样,用 kubectl apply -f 就能部署和运行一个分布式应用, 而无需关心是在私有云还是公有云以及具体哪家云厂商上,Kubernetes 的 API 框架已经屏蔽了这些细节。因此,Kubernetes 并不是关于容器的,而是关于 API。— 2 —Kubernetes 的 API 类型 可以通过 GET/LIST/PUT/POST/DELETE 等 API 操作,来创建、查询、修改或删除集群中的资源。各 controller **到资源变化时,就会执行相应的 reconcile 逻辑,来使 status 与 spec 描述相符。标准 API(针对内置资源类型)‍Namespaced 类型,这种类型的资源是区分 namespace,也就是可以用 namespace 来隔离。大部分内置资源都是这种类型,包括:podsservicesnetworkpoliciesAPI 格式:格式:/api/{version}/namespaces/{namespace}/{resource}举例:/api/v1/namespaces/default/podsUn-namespaced 类型,这种类型的资源是全局的,不能用 namespace 隔离,例如:nodesclusterroles(clusterxxx 一般都是,表示它是 cluster-scoped 的资源)API 格式:格式:/api/{version}/{resource}举例:/api/v1/nodes扩展 API(apiextension)1、Namespaced 类型API 格式:格式:/apis/{apiGroup}/{apiVersion}/namespaces/{namespace}/{resource}举例:/apis/cilium.io/v2/namespaces/kube-system/ciliumnetworkpolicies2、Un-namespaced 类型CRD用户发现了 Kubernetes 的强大之后,希望将越来越多的东西(数据)放到 Kubernetes 里面, 像内置的 Pod、Service、NetworkPolicy 一样来管理,因此出现了两个东西:CRD:用来声明用户的自定义资源,例如它是 namespace-scope 还是 cluster-scope 的资源、有哪些字段等等,Kubernetes 会自动根据这个定义生成相应的 API;官方文档的例子[1], 后文也将给出一个更简单和具体的例子。CRD 是资源类型定义,具体的资源叫 CR。Operator 框架:“Operator” 在这里的字面意思是“承担运维任务的程序”, 它们的基本逻辑都是一样的:时刻盯着资源状态,一有变化马上作出反应(也就是 reconcile 逻辑)。这就是扩展 API 的(最主要)声明和使用方式。至此,我们讨论的都是一些比较抽象的东西,接下来通过一些例子和类比来更直观地理解一下。— 3 —直观类比:Kubernetes 是个数据库,CRD 是一张表,API 是 SQL 在本节中,我们将创建一个名为 fruit 的 CRD,它有 name/sweet/weight 三个字段, 完整 CRD 如下:apiVersion: apiextensions.k8s.io/v1kind: CustomResourceDefinitionmetadata:  name: fruits.example.org        # CRD 名字spec:  conversion:    strategy: None  group: example.org              # REST API: /apis/<group>/<version>  names:    kind: Fruit    listKind: FruitList    plural: fruits    singular: fruit  scope: Namespaced               # Fruit 资源是区分 namespace 的  versions:  - name: v1                      # REST API: /apis/<group>/<version>    schema:      openAPIV3Schema:        properties:          spec:            properties:              comment:            # 字段 1,表示备注                type: string              sweet:              # 字段 2,表示甜否                type: boolean              weight:             # 字段 3,表示重量                type: integer            type: object        type: object    served: true                  # 启用这个版本的 API(v1)    storage: true    additionalPrinterColumns:     # 可选项,配置了这些 printer columns 之后,    - jsonPath: .spec.sweet       # 命令行 k get <crd> <cr> 时,能够打印出下面这些字段,      name: sweet                 # 否则,k8s 默认只打印 CRD 的 NAME 和 AGE      type: boolean    - jsonPath: .spec.weight      name: weight      type: integer    - jsonPath: .spec.comment      name: comment      type: string后面会解释每个 section 都是什么意思。在此之前,先来做几个(直观而粗糙的)类比。Kubernetes 是个数据库像其他数据库技术一样,它有自己的持久存储引擎(etcd),以及构建在存储引擎之上的 一套 API 和语义。这些语义允许用户创建、读取、更新和删除(CURD)数据库中的数据。下面是一些概念对应关系:关系型数据库Kubernetes(as a database)说明DATABASEcluster一套 Kubernetes 集群就是一个 database 【注 1】TABLEKind每种资源类型对应一个表;分为内置类型和扩展类型 【注 2】COLUMNproperty表里面的列,可以是 string、boolean 等类型rowsresources表中的一个具体 record表中的一个具体 record【注 1】 如果只考虑 namespaced 资源的话,也可以说一个 namespace 对应一个 database。【注 2】 前面已经介绍过,内置 Kind:Job、Service、Deployment、Event、NetworkPolicy、Secret、ConfigMap 等等;扩展 Kind:各种 CRD,例如 CiliumNetworkPolicy。所以,和其他数据库一样,本质上 Kubernetes 所做的不过是以 schema 规定的格式来处理 records。另外,Kubernetes 的表都有自带文档‍:$ k explain fruitsKIND:     FruitVERSION:  example.org/v1DESCRIPTION:     <empty>FIELDS:   apiVersion   <string>     APIVersion defines the versioned schema of this representation of an     object. Servers should convert recognized schemas to the latest internal     value, and may reject unrecognized values. More info:     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources   kind <string>     Kind is a string value representing the REST resource this object     represents. Servers may infer this from the endpoint the client submits     requests to. Cannot be updated. In CamelCase. More info:     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds   metadata     <Object>     Standard object's metadata. More info:     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata   spec <Object>另外,Kubernetes API 还有两大特色:极其可扩展:声明 CRD 就会自动创建 API;支持事件驱动。CRD 是一张表CRD 和内置的 Pod、Service、NetworkPolicy 一样,不过是数据库的一张表。例如,前面给出的 fruit CRD,有 name/sweet/weight 列,以及 “apple”、“banana” 等 entry。用户发现了 Kubernetes 的强大,希望将越来越多的东西(数据)放到 Kubernetes 里面来管理。数据类 型显然多种多样的,不可能全部内置到 Kubernetes 里。因此,一种方式就是允许用户创建自己的 “表”,设置自己的“列” —— 这正是 CRD 的由来。1、定义表结构(CRD spec)CRD(及 CR)描述格式可以是 YAML 或 JSON。CRD 的内容可以简单分为三部分:常规 Kubernetes metadata:每种 Kubernetes 资源都需要声明的字段,包括 apiVersion、kind、metadata.name 等‍‍。 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata:   name: fruits.example.org        # CRD 名字Table-level 信息:例如表的名字,最好用小写,方便以后命令行操作‍; spec:   conversion:     strategy: None   group: example.org              # REST API: /apis/<group>/<version>   names:     kind: Fruit     listKind: FruitList     plural: fruits     singular: fruit   scope: Namespaced               # Fruit 资源是区分 namespace 的Column-level 信息:列名及类型等等,遵循 OpenAPISpecification v3 规范。   versions:   - name: v1                      # REST API: /apis/<group>/<version>     schema:       openAPIV3Schema:         properties:           spec:             properties:               comment:            # 字段 1,表示备注                 type: string               sweet:              # 字段 2,表示甜否                 type: boolean               weight:             # 字段 3,表示重量                 type: integer             type: object         type: object     served: true                  # 启用这个版本的 API(v1)     storage: true     additionalPrinterColumns:     # 可选项,配置了这些 printer columns 之后,     - jsonPath: .spec.sweet       # 命令行 k get <crd> <cr> 时,能够打印出下面这些字段,       name: sweet                 # 否则,k8s 默认只打印 CRD 的 NAME 和 AGE       type: boolean     - jsonPath: .spec.weight       name: weight       type: integer     - jsonPath: .spec.comment       name: comment       type: string2、测试:CR 增删查改 vs. 数据库 SQL创建 CRD:这一步相当于 CREATE TABLE fruits ...;。 $ kubectl create -f fruits-crd.yaml customresourcedefinition.apiextensions.k8s.io/fruits.example.org created创建 CR:相当于 INSERT INTO fruits values(...);。apple-cr.yaml‍: apiVersion: example.org/v1 kind: Fruit metadata:   name: apple spec:   sweet: false   weight: 100   comment: little bit rottenbanana-cr.yaml: apiVersion: example.org/v1 kind: Fruit metadata:   name: banana spec:   sweet: true   weight: 80   comment: just bought创建‍: $ kubectl create -f apple-cr.yaml fruit.example.org/apple created $ kubectl create -f banana-cr.yaml fruit.example.org/banana created查询 CR:相当于 SELECT * FROM fruits ... ; 或 SELECT * FROM fruits WHERE name='apple';。 $ k get fruits.example.org # or kubectl get fruits NAME     SWEET   WEIGHT   COMMENT apple    false   100      little bit rotten banana   true    80       just bought $ kubectl get fruits apple NAME    SWEET   WEIGHT   COMMENT apple   false   100      little bit rotten删除 CR:相当于 DELETE FROM fruits WHERE name='apple';。 $ kubectl delete fruit apple可以看到,CRD/CR 的操作都能对应到常规的数据库操作。API 是 SQL上一节我们是通过 kubectl 命令行来执行 CR 的增删查改,它其实只是一个外壳,内部 调用的是 Kubernetes 为这个 CRD 自动生成的 API —— 所以又回到了本文第一节论述的内容:Kubernetes 的核心是其 API 框架。只要在执行 kubectl 命令时指定一个足够大的 loglevel,就能看到背后的具体 API 请求。例如:$ kubectl create -v 10 -f apple-cr.yaml  ...  Request Body: {"apiVersion":"example.org/v1","kind":"Fruit",\"spec\":{\"comment\":\"little bit rotten\",\"sweet\":false,\"weight\":100}}\n"},"name":"apple","namespace":"default"},"spec":{"comment":"little bit rotten","sweet":false,"weight":100}}  curl -k -v -XPOST 'https://127.0.0.1:6443/apis/example.org/v1/namespaces/default/fruits?fieldManager=kubectl-client-side-apply'  POST https://127.0.0.1:6443/apis/example.org/v1/namespaces/default/fruits?fieldManager=kubectl-client-side-apply 201 Created in 25 milliseconds  ...— 4 —其他 给 CR 打标签(label),根据 label 过滤和内置资源类型一样,Kubernetes 支持对 CR 打标签,然后根据标签做过滤:# 查看所有 frutis$ k get fruitsNAME     SWEET   WEIGHT   COMMENTapple    false   100      little bit rottenbanana   true    80       just bought# 给 banana 打上一个特殊新标签$ k label fruits banana tastes-good=truefruit.example.org/banana labeled# 按标签筛选 CR$ k get fruits -l tastes-good=trueNAME     SWEET   WEIGHT   COMMENTbanana   true    80       just bought# 删除 label$ k label fruits banana tastes-good-fruit.example.org/banana labeledKubernetes API 与鉴权控制(RBAC)不管是内置 API,还是扩展 API,都能用 Kubernetes 强大的 RBAC 来做鉴权控制。关于如何使用 RBAC 网上已经有大量文档;但如果想了解其设计,可参考 Cracking Kubernetes RBAC Authorization Model[2], 它展示了如何从零开始设计出一个 RBAC 鉴权模型(假设 Kubernetes 里还没有)。相关链接:https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#create-a-customresourcedefinitionhttps://arthurchiao.art/blog/cracking-k8s-authz-rbac/参考链接:https://blog.joshgav.com/2021/12/16/kubernetes-isnt-about-containers.htmlhttps://github.com/gotopple/k8s-for-users-intro/blob/master/database.mdhttps://itnext.io/crd-is-just-a-table-in-kubernetes-13e15367bbe4原文阅读:https://mp.weixin.qq.com/s/MEhDJYg_lmjbPEdFFLdedg
  • [沙箱纠错] 基于CCE Kubernetes编排实战_步骤
    我1.1和1.2明明都购买完了为什么不显示已完成?
  • [沙箱纠错] 基于CCE Kubernetes编排实战_步骤
    无法按需计费
  • [技术干货] 搭建高可用kubernetes集群(keepalived+haproxy)
    haproxy:达到负载均衡的目的,通过配置虚拟ipkeepalived:检测主机是否存活准备三台机器,ip的划分如下参考《k8s集群的搭建》搭建好k8s集群:https://bbs.huaweicloud.com/forum/forum.php?mod=viewthread&tid=120441第一步、在master2节点安装docker 第二步、在master2节点上安装k8s基础组件(所有节点)1、启用NET.BRIDGE.BRIDGE-NF-CALL-IPTABLES内核选项sysctl -w net.bridge.bridge-nf-call-iptables=1# 关闭防火墙systemctl stop firewalldsystemctl disable firewalld # 关闭selinuxsed -i 's/enforcing/disabled/' /etc/selinux/config  # 永久setenforce 0  # 临时2、禁用交换分区。swapoff -acp -p /etc/fstab /etc/fstab.bak$(date '+%Y%m%d%H%M%S')sed -i "s/\/dev\/mapper\/centos-swap/\#\/dev\/mapper\/centos-swap/g" /etc/fstab3、安装K8s组件。yum install -y kubelet kubeadm kubectl kubernetes-cni4、查看安装情况。rpm -qa | grep kubeletrpm -qa | grep kubeadmrpm -qa | grep kubectlrpm -qa | grep kubernetes-cni5、设置iptables。echo "net.bridge.bridge-nf-call-iptables=1" > /etc/sysctl.d/k8s.conf6、使能kubelet服务。systemctl enable kubelet 第三步、在两个master01和master02节点都安装keepalived+haproxyyum install -y conntrack-tools libseccomp libtool-ltdl keepalived  第四步、# 根据规划设置主机名hostnamectl set-hostname <hostname># 在集群的所有节点添加hostscat >> /etc/hosts << EOF10.10.9.16   master-0110.10.9.130   node-0110.10.9.219    master-02EOF ### 3.2配置master节点 master1节点配置 ```cat > /etc/keepalived/keepalived.conf <<EOF ! Configuration File for keepalived global_defs {   router_id master-01} vrrp_script check_haproxy {    script "killall -0 haproxy"    interval 3    weight -2    fall 10    rise 2} vrrp_instance VI_1 {    state MASTER    interface enp3s0    virtual_router_id 51    priority 100    advert_int 1    authentication {        auth_type PASS        auth_pass 111    }    virtual_ipaddress {        10.10.9.220    }    track_script {        check_haproxy    } }EOF``` master2节点配置 ```cat > /etc/keepalived/keepalived.conf <<EOF ! Configuration File for keepalived global_defs {   router_id master-02} vrrp_script check_haproxy {    script "killall -0 haproxy"    interval 3    weight -2    fall 10    rise 2} vrrp_instance VI_1 {    state BACKUP    interface enp3s0    virtual_router_id 51    priority 90    advert_int 1    authentication {        auth_type PASS        auth_pass 111    }    virtual_ipaddress {        10.10.9.220    }    track_script {        check_haproxy    } }EOF``` ### 3.3 启动和检查 在两台master节点都执行 ```# 启动keepalived$ systemctl start keepalived.service设置开机启动$ systemctl enable keepalived.service# 查看启动状态$ systemctl status keepalived.service```  启动后查看master1的网卡信息 ```ip a s enp3s0  多一个虚拟ip在master01节点。当master01节点挂之后,虚拟ip会漂移到master02节点说明:检查keepalived是否安装成功的标准是:1.任何一台服务器上ping虚拟ip可以通;2.虚拟IP只在一台服务上可见;3.任意停止某一台服务器后,虚拟IP会移动到剩下的某一台服务器上,并正常使用。 ## 4. 在两个主节点安装haproxyyum install -y haproxy ### 4.2 配置 两台master节点的配置均相同,配置中声明了后端代理的两个master节点服务器,指定了haproxy运行的端口为6444等,因此6444端口为集群的入口 ```cat > /etc/haproxy/haproxy.cfg << EOF#   https://www.haproxy.org/download/1.8/doc/configuration.txt##--------------------------------------------------------------------- global    log         127.0.0.1 local2    chroot      /var/lib/haproxy    pidfile     /var/run/haproxy.pid    user        haproxy    group       haproxy    daemon    maxconn     4000 defaults    mode                    http    log                     global    option                  httplog    option                  dontlognull    retries                 3    timeout http-request    5s    timeout queue           1m    timeout connect         5s    timeout client          1m    timeout server          1m    timeout http-keep-alive 5s    timeout check           5s    maxconn                 3000  frontend kubernetes-apiserver    mode                 tcp    bind                 *:6444  # 对外提供服务的端口,必须和kubernetes一致    option               tcplog    default_backend      kubernetes-apiserver #后端服务的名称 backend kubernetes-apiserver    mode        tcp    balance     roundrobin    server  master-01 10.10.9.16:6443 check # 后端服务器hostname和IP    server  master-02 10.10.9.219:6443 check # 后端服务器hostname和IPEOF``` ### 4.3两台master都启动# 设置开机启动$ systemctl enable haproxy# 开启haproxy$ systemctl start haproxy# 查看启动状态$ systemctl status haproxy```检查端口```netstat -lntup|grep haproxy```## 8、master2节点加入集群时间同步:yum install ntpdate -y && timedatectl set-timezone Asia/Shanghai  && ntpdate time.windows.com 7.6 添加其他master节点将node-01将证书文件拷贝至其他master节点 mkdir -p /etc/kubernetes/pki/etcdscp /etc/kubernetes/admin.conf root@10.10.9.219:/etc/kubernetes/admin.conf scp /etc/kubernetes/pki/{ca.*,sa.*,front-proxy-ca.*} root@10.10.9.219:/etc/kubernetes/pki scp /etc/kubernetes/pki/etcd/ca.* root@10.10.9.219:/etc/kubernetes/pki/etcd   ### 8.2 master2加入集群执行在master1上init后输出的join命令,需要带上参数`--control-plane`表示把master控制节点加入集群kubeadm join 10.10.9.220:6444 --token abcdef.0123456789abcdef \    --discovery-token-ca-cert-hash sha256:5bd9f4b5fbf4e15a34c03159a5c4343d2261b4b2740101298a307f0ac4a1bc59 \--experimental-control-plane  在master02节点下载对应的docker镜像 在master02节点执行步骤2中需要的步骤(k8s基础步骤)echo "1" > /proc/sys/net/ipv4/ip_forward      在master-01节点运行:kubeadm init phase upload-certs --experimental-upload-certs获取k8s加入集群的token kubeadm token create --print-join-command把上面两个输出结果合拼为一条命令。在master-02上执行kubeadm join 10.10.9.220:6444 --token abcdef.0123456789abcdef \    --discovery-token-ca-cert-hash sha256:5bd9f4b5fbf4e15a34c03159a5c4343d2261b4b2740101298a307f0ac4a1bc59 \--experimental-control-plane 配置中的sever需要机器的ip地址sudo cat /etc/kubernetes/kubelet.confhttps://www.jianshu.com/p/745c96476a32 k8s中初始化的yaml文件kubeadm config print init-defaults > kubeadm-config.yaml配置文件如下:apiVersion: kubeadm.k8s.io/v1beta1bootstrapTokens:- groups:  - system:bootstrappers:kubeadm:default-node-token  token: abcdef.0123456789abcdef  ttl: 24h0m0s  usages:  - signing  - authenticationkind: InitConfigurationlocalAPIEndpoint:  advertiseAddress: 10.10.9.16  bindPort: 6443nodeRegistration:  criSocket: /var/run/dockershim.sock  name: master-01  taints:  - effect: NoSchedule    key: node-role.kubernetes.io/master---apiServer:  timeoutForControlPlane: 4m0sapiVersion: kubeadm.k8s.io/v1beta1certificatesDir: /etc/kubernetes/pkiclusterName: kubernetescontrolPlaneEndpoint: "10.10.9.220:6444"controllerManager: {}dns:  type: CoreDNSetcd:  local:    dataDir: /var/lib/etcdimageRepository: k8s.gcr.iokind: ClusterConfigurationkubernetesVersion: v1.14.2networking:  dnsDomain: cluster.local  podSubnet: "10.244.0.0/16"  serviceSubnet: 10.96.0.0/12scheduler: {} 初始化集群kubeadm init --config  kubeadm-config.yaml 附:配置免密登录a、生成密钥,遇到提示时,按回车。ssh-keygen -t rsa会在/root/.ssh文件下生成如下文件b、在每台机器上配置SSH免密登录(包括配置自身节点的免密)。ssh-copy-id -i ~/.ssh/id_rsa.pub root@所有节点IP会在/roo/.ssh/authorized_keys里面追加公钥验证:ssh ip地址 直接进入所在的服务器 清空集群kubeadm reset启动集群systemctl enable kubelet && systemctl start kubelet初始化kubeadm init --config kubeadm-config.yml# 1.从master节点拷贝配置文件到准备添加的节点上mkdir -p /etc/kubernetes/pki/etcdscp /etc/kubernetes/admin.conf root@10.10.9.219:/etc/kubernetes/admin.conf scp /etc/kubernetes/pki/{ca.*,sa.*,front-proxy-ca.*} root@10.10.9.219:/etc/kubernetes/pki scp /etc/kubernetes/pki/etcd/ca.* root@10.10.9.219:/etc/kubernetes/pki/etcd mkdir -p /etc/kubernetes/pki/etcdscp /etc/kubernetes/admin.conf root@10.10.9.130:/etc/kubernetes/admin.confscp /etc/kubernetes/pki/{ca.*,sa.*,front-proxy-ca.*} root@10.10.9.130:/etc/kubernetes/pkiscp /etc/kubernetes/pki/etcd/ca.* root@10.10.9.130:/etc/kubernetes/pki/etcd 查看kubelet详细报错信息journalctl -xefu kubelet 查看kubelet状态systemctl status kubeletkubeadm join 10.10.17.68:6443 --token 4y6qqt.c79h5g8k24peruxd \    --discovery-token-ca-cert-hash sha256:bd27d56ec229d75f83787a199523728df3cf4d83623041d284f38695a28686d8 --experimental-control-plane [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'error execution phase preflight: unable to fetch the kubeadm-config ConfigMap: failed to get config map: Get https://10.10.9.220:6444/api/v1/namespaces/kube-system/configmaps/kubeadm-config: dial tcp 10.10.9.220:6444: i/o timeout更多请参考:https://www.cnblogs.com/chusiyong/p/12838111.html
  • [知识分享] 解构HE2E中的Kubernetes技术应用
    本文分享自华为云社区《[解构HE2E中的Kubernetes技术应用](https://bbs.huaweicloud.com/blogs/352564?utm_source=csdn&utm_medium=bbs-ex&utm_campaign=paas&utm_content=content)》,作者: 敏捷小智 。 在《[解构HE2E中的容器技术应用](https://bbs.huaweicloud.com/blogs/345979)》 一文当中,为大家分析了HE2E项目的代码仓库、编译构建、部署等各环节中对于容器技术的应用。今天,我们将从Kubernetes技术应用的角度解构[华为云 DevCloud HE2E DevOps实践](https://support.huaweicloud.com/bestpractice-devcloud/devcloud_practice_2000.html) 。 # 什么是Kubernetes? Kubernetes (也称K8S)是用于自动部署,扩展和管理容器化应用程序的开源系统。 # K8S与CCE 在上一篇文章中,大家已经了解了HE2E项目中通过Docker实现容器化部署,在该实践中通过此方式部署至ECS弹性云服务器中,并称之为ECS部署。在该实践中,提供了另外一套部署方式,将应用部署至CCE集群当中,即CCE部署,使用的工具即K8S。 总之,根据部署目标的不同,HE2E实践中分别介绍了ECS部署与CCE部署。根据部署采用的技术工具不同,也可以将这两种方式称为Docker部署与K8S部署。 # 为什么选择K8S 在正式的生产环境中,企业和团队往往会需要将应用部署至多个服务器主机,而CCE集群和K8S则共同为应用的部署、运行及管理提供了保障。相较而言,HE2E实践中介绍的ECS部署方式更倾向于开发、测试等环境下的单机部署。 # K8S的代码配置 回到项目本身,代码仓库中的./kompose/文件夹下有多个yaml文件。可以看出,每个服务都有两个配置文件(*-deployment.yaml与*-service.yaml)共同进行配置。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20225/20/1653013720068215690.png) 此处以db-deployment.yaml为例,对yaml配置仅作简短的介绍,帮助大家理解配置内容。随着集群版本和产品能力的更迭,也有很多配置信息将发生变化。所以在实践当中,需要调整 yaml 文件配置 。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20225/20/1653013729254244601.png) • apiVersion:此处值为apps/v1,这个版本号需要根据安装的K8S版本和资源类型进行变化。目前实践中对应v1.19版本的K8S集群。 • kind:此处创建的是Deployment,根据实际情况,此处资源类型可以是Pod、Job、Ingress、Service等。如:在*-service.yaml文件中,创建的资源类型则是Service。 • metadata:包含Deployment的一些meta信息。其中,annotations的含义是注解。 • spec:你所期望的该对象的状态。包括replicas、selector、containers等Kubernetes需要的参数。其中,containers定义了该deployment使用的镜像:docker-server/docker-org/postgres:9.4。在上篇文章中提到过,这里的docker-server、docker-org都会在构建任务中替换为实际镜像对应的镜像地址和组织。strategy、restartPolicy等字段共同构成了容器失败时重启的策略。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20225/20/1653013738056986003.png) 在*-service.yaml当中,主体内容与*-deployment.yaml相差也不算大,主要差异集中于spec这部分。*-service.yaml对应的spec主要是定义了集群内访问的方式,使各个服务之间可以互相访问。 可以看出,*-deployment.yaml 与*-service.yaml共同定义了一个服务*。*-deployment.yaml主要定义了该服务的镜像源,或者说工作负载是什么。而*-service.yaml则定义了该服务访问方式。 # K8S的部署配置 在编译构建环节,主体还是制作镜像上传到SWR镜像仓库,与上篇文章的没有区别。相关的配置文件也通过构建任务上传到软件发布库了,所以这里就不赘述了。 镜像、配置和集群资源都准备妥当以后,就是使用K8S部署的环节了。 # - 代理机配置 我们在HE2E实践中采用的是代理机的部署方式,将集群中的一个节点作为代理机进行授信、部署。所以在实践中我们从集群下载Kubectl配置文件并配置到节点主机当中(见《配置 Kubectl 》)。通过配置Kubectl的操作,我们就可以在节点主机上执行命令进而影响整个CCE集群。 # - CCE部署任务 HE2E实践中,phoenix-cd-cce是我们所需执行的部署任务。该任务将配置文件传输到目标主机,即代理机、集群节点。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20225/20/1653013776192877195.png) 而后,通过执行shell命令启动Kubenetes。 kubectl delete secret regcred kubectl create secret docker-registry regcred --docker-server=${docker-server} --docker-username=${docker-username} --docker-password=${docker-password} --docker-email=***@***.cn kubectl delete -f /root/phoenix-sample-deploy/kompose/ kubectl apply -f /root/phoenix-sample-deploy/kompose/ • 这里先是删除原有的secret,这一步主要是为了防止由于使用临时登录命令变化而导致secret错误引发的任务执行失败。 • 接着,创建新的secret。包含docker-server、docker-username、docker-password等信息。 • 按配置文件(/root/phoenix-sample-deploy/kompose/)删除资源。 • 按配置文件(/root/phoenix-sample-deploy/kompose/)对资源进行配置。 成功执行该部署任务后,可以在CCE集群中看到五个工作负载已经处于“运行中”的状态。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20225/20/1653013791361975806.png) 不过目前还需要设置“节点访问”才能正常访问。所以在后续实践中对工作负载vote和result手动添加访问方式。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20225/20/1653013798245600410.png) 节点访问设置完毕后,即可访问项目的用户端与管理端了。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20225/20/1653013805736917160.png) ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20225/20/1653013823631945942.png) # K8S的模板部署方式 理论上,讲到现在,HE2E实践中的K8S部署就已经讲完了。但是,笔者猜到,肯定有很多人不喜欢这种通过代理机部署集群的方式。不过没关系,下面我就来介绍DevCloud当中的Kubernetes模板部署。 新建模板时,现在可以选择模板:Kubernetes部署。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20225/20/1653013841694495933.png) 进入模板以后,可以选择集群类型、区域、命名空间、部署方式等信息。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20225/20/1653013852227197420.png) 由于本项目通过10个yaml文件共同配置,所以需要添加相同的“Kubernetes部署”步骤共计10个,每个步骤都对应一个yaml文件。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20225/20/1653013861289828309.png) 而由于我们在代码仓库中的配置并非我们最终部署时所需的配置(经过编译构建修改docker-server等参数),所以我们需要每个步骤都设置软件发布库中对应的yaml文件。此时,我们会发现,我们原本的构建任务是将所有yaml文件进行了打包压缩后才上传的,没有办法直接选中。所以,我们可以再次创建一个构建任务或者在原有构建任务上进行修改,以使软件发布库中存放有所有的yaml文件。 构建任务上传步骤的配置参考:(上传所有yaml文件而非打包后上传) ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20225/20/1653013872326397506.png) 完成以上配置以后,执行Kubernetes部署模板任务,即可将服务部署至选定的CCE集群当中。此时再添加节点访问方式即可访问用户端与管理端。 当然,我们也可以将节点访问也写入yaml文件中,实现进一步的一键部署。这里就暂且留作一个小思考题,感兴趣的小伙伴可以自己尝试一下,将节点访问写入yaml当中。 # 结语 本篇文章一面介绍了HE2E实践中的CCE部署方式,一面又介绍了该实践中未提到的Kubernetes模板部署。两者的主要区别是“CCE部署”是通过代理机控制集群进行K8S部署;Kubernetes模板部署则是直接在集群中部署。此外,本文也对项目中关于K8S的配置进行了一定程度的解析。
  • [认证交流] 华为云云原生入门级开发者认证学习笔记——第三章_细化刷新
    第三章:云原生基础设施之Kubernetes学习笔记容器集群管理概述• 容器编排指自动化容器的部署、管理、扩展和联网,其价值:    灵活的资源管理及调度;    自动化部署及服务发现;    高效的监控及运维;    弹性扩展及高可用。• 从Borg到Kubernetes:起源于google内部Borg项目,于2015年7月22日迭代到v1.0并正式对外公布。• 2017年10月17日Docker宣布支持Kubernetes。Kubernetes核心架构与理念• 下图展现K8S的架构和工作流程• 基础的K8s集群通常包含一个Master节点和多个Node节点,每个节点可以是物理机也可以是虚拟机。• Master节点:提供的集群控制,对集群做出全局性决策Kube-apiserver:对外暴露K8s API,接收外部请求,写入etcd,可水平扩展;etcd:分布式数据存储组件,存储集群配置数据,提供数据备份Kube-controller-manager:控制器,执行集群级功能,例如复制组件,跟踪Node节点,处理节点故障等Kube-scheduler:负责任务调度,根据各种条件(如可用的资源、节点的亲和性等)将容器调度到Node上运行• Node节点:运行容器应用,根据Master的要求管理容器的生命周期Kubelet:接受Master指令,负责管理容器(Pod)Kube-proxy:应用组件间的访问代理,解决节点上应用的访问问题    Add-ons:插件,用于扩展K8s的功能Container runtime:容器运行时,如Docker,最主要的功能是下载镜像和运行容器。• 开放接口CRI、CNI、CSICRI:容器运行时的接口,提供计算能力CNI:容器网络接口,提供网络能力CSI:容器存储接口,提供存储能力• K8s工作流程• K8s核心概念:Pod:最小工作单元,每一个Pod包含一个或多个相关容器,K8s将其视为一个整体进行调度。引入Pod目的:扩展和实现生命周期管理。相同POD内的容器:使用相同的namespace空间,即有相同的IP地址和port,使用同一个localhost,volume可挂载到所有pod内的容器实现共享。但pod中每个容器的cpu和memory等资源通过其自身cgroup来做限制。Label:为资源打上标签,方便分类管理Namespace:在集群中对资源进行组织上的隔离。四个默认namespace:default、kube-public(公共访问区)、kube-system(系统资源区,如kubelet、kubeproxy等)、kube-node-lease。每个资源仅属于一个namespace,不同namespace中的资源命名可以相同;通过ResouceQuota做资源限制;全局资源不属于某一个namespaceConroller:控制器,K8S通过控制器管理PodService:定义Pod逻辑集合及访问策略,为Pod提供了负载均衡,通过label来选择Pod。Volume:管理Kubernetes存储,声明Pod中容器可以访问的文件目录,需挂载。Kubernetes应用编排与管理• Kubectl:K8s的命令行工具;指令式:kubectl [command] [TYPE] [NAME] [flags]声明式:kubectl apply –f [yaml文件名] .yaml文件的必选配置字段:apiVersion,kind,metadata,spec• YAML的语法规则Label的形式为key-value形式大小写敏感使用缩进表示层级关系,缩进使用空格而非tab,相同层级的元素左侧对齐在同一个yaml配置文件内可以同时定义多个资源• Kubernetes管理的对象类型总览:• 状态工作负载:Deployment、ReplicaSet• Deployment控制器下的每个Pod除了名称和IP地址不同,其余完全相同。Deployment可以根据需要同故宫Pod模板创建Pod或者删除任意一个Pod。• ReplicaSet,确定Deployment中Pod的副本数量• 从大到小的管理逻辑为:Deployment>ReplicaSet>Pod>容器• 创建Deployment指令式:kubectl create deployment deployment_name --image=image_name –replicas=number声明式:vi filename.yaml [注意,此处 kind: Deployment]                       Kubectl apply –f filename.yaml• 查看deployment创建情况:kubectl get deployment• 滚动更新:使用新的实例逐步更新Pod实例,零停机进行工作负载的更新。更新Deployement:kubectl edit deploy nginxkubectl set image deploy nginx nginx=nginx:1.9.1 kubectl apply -f nginx.yaml    • 查看Deployment滚动更新情况/历史:kubectl rollout status deploy nginxkubectl rollout history deploy nginx• 回滚:kubectl rollout pause deploy nginxkubectl rollout resume deploy nginx• 有状态工作负载:StatefulSet:StatefulSet给每个Pod提供固定名称,Pod名称增加从0-N的固定后缀,Pod重新调度后Pod名称和HostName不变。StatefulSet通过Headless Service给每个Pod提供固定的访问域名。每个Pod有单独存储,StatefulSet通过创建固定标识的PVC保证Pod重新调度后还是能访问到相同的持久化数据。创建StatefulSet,yaml文件指定kind为StatefulSet,并指定volumeMounts• 守护进程工作负载:DaemonSetDaemonSet(守护进程集)在集群的每个节点上运行一个Pod,且保证只有一个Pod,适合系统层面的应用,例如日志收集、资源监控等Yaml文件创建DaemonSet时,kind选择DaemonSet,不需要规定replicas项。• Jobs:主要处理短暂的一次性任务,Job管理的Pod根据用户的设置把任务成功完成就自动退出(Pod自动删除),Jobs特点:保证指定数量Pod成功运行结束。支持并发执行。支持错误自动重试。支持暂停/恢复Jobs。• 创建JobsKind选择Job。Completions当前的任务需要执行的Pod数量。Parallelism表示最多有多少个并发执行的任务。RestartPolicy只能选择Never或OnFailure。BackoffLimit参数指定job失败后进行重试的次数。• CronJob:处理周期性或者重复性的任务,可使用Cron格式快速指定任务的调度时间,在yaml文件中kind选择CronJob,spec中的schedule: "* * * * *" 用来进行配置┌───────────── minute (0 - 59)│ ┌───────────── hour (0 - 23)│ │ ┌───────────── day of the month (1 - 31)│ │ │ ┌───────────── month (1 - 12)│ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;│ │ │ │ │ 7 is also Sunday on some systems)│ │ │ │ ││ │ │ │ │* * * * *    如果您想要每个月的第一天里面每半个小时执行一次,那就可以设置为" 0,30 * 1 * * " 如果您想每个星期天的3am执行一次任务,那就可以设置为 "0 3 * * 0"。Kubernetes服务发布• Pod特征:有独立IP、扩缩容时数量会变更、故障时ReplicaSet会创建新的Pod• Service定义了访问逻辑上一组Pod的策略,有如下如所示3种类型• ClusterIP:提供一个集群内部的虚拟IP地址以供Pod访问(默认模式)• NodePort:在Node上打开一个端口以供外部访问• LoadBalance:通过外部的负载均衡器来访问。如果创建一个LoadBalancer,系统则会创建一个NodePort,NodePort则会创建ClusterIP。• Ingress:七层负载均衡,基于七层的HTTP和HTTPS协议进行转发Ingress资源:一组基于域名或URL把请求转发到指定Service实例的访问规则,是Kubernetes的一种资源对象,通过接口服务实现增、删、改、查的操作。Ingress Controller:请求转发的执行器,用以实时监控资源对象Ingress、Service、End-point、Secret(主要是TLS证书和Key)、Node、ConfigMap的变化,解析Ingress定义的规则并负责将请求转发到相应的后端Service。Ingress Controller在不同厂商之间的实现方式不同,根据负载均衡器种类的不同,可以将其分成ELB型和Nginx型。Kubernetes存储管理• Volume的核心是一个目录,用于Pod中的容器共享文件,与挂在它的Pod的生命周期相同。Pod不存在时,临时卷类型(emptyDir、ConfigMap、Secret等)中的数据会被销毁,持久化存储的卷(hostPath、PVC等)中的数据会保存。Volume不能独立创建,只能在Pod中定义。• emptyDir:一种简单的空目录,主要用于临时存储,适用于缓存空间,日志采集等场景。• ConfigMap:用于存储应用所需配置信息(key-value 形式)的资源类型,在被Pod引用前需单独定义。在Volume中引用ConfigMap:就是通过文件的方式直接将ConfigMap的每条数据填入Volume,每条数据是一个文件,键就是文件名,键值就是文件内容。• Secret:与ConfigMap类似,都是key-value键值对形式,使用方式也相同;Secret会加密存储,所以适用于存储敏感信息。只有Pod请求的Secret在其容器中才是可见的,一个Pod不能访问另一个Pod的Secret。• hostPath:能将主机节点文件系统上的文件或目录挂载到Pod中。适用于读取主机上的数据。永远不要使用HostPath存储跨Pod的数据。• PersistentVolume:PV描述的是持久化存储卷,主要定义的是一个持久化存储在宿主机上的目录,比如一个NFS的挂载目录。• PersistentVolumeClaim:PVC描述的是Pod所希望使用的持久化存储的属性,比如,Volume存储的大小、可读写权限等等。• StorageClass:存储类,简称SC,为管理员提供了描述存储 “类” 的方法,通过相应的存储插件(CSI)实现,可根据用户提出的PVC动态提供不同性质的PV。
  • [技术干货] 解构HE2E中的Kubernetes技术应用[转载]
    链接:https://bbs.huaweicloud.com/blogs/352564在《解构 H E2E 中的容器技术应用》 一文当中,为大家分析了HE2E项目的代码仓库、编译构建、部署等各环节中对于容器技术的应用。今天,我们将从Kubernetes技术应用的角度解构华为云 DevCloud HE2E D evOps 实践 。什么是Kubernetes?Kubernetes (也称K8S)是用于自动部署,扩展和管理容器化应用程序的开源系统。K8S与CCE在上一篇文章中,大家已经了解了HE2E项目中通过Docker实现容器化部署,在该实践中通过此方式部署至ECS弹性云服务器中,并称之为ECS部署。在该实践中,提供了另外一套部署方式,将应用部署至CCE集群当中,即CCE部署,使用的工具即K8S。总之,根据部署目标的不同,HE2E实践中分别介绍了ECS部署与CCE部署。根据部署采用的技术工具不同,也可以将这两种方式称为Docker部署与K8S部署。为什么选择K8S在正式的生产环境中,企业和团队往往会需要将应用部署至多个服务器主机,而CCE集群和K8S则共同为应用的部署、运行及管理提供了保障。相较而言,HE2E实践中介绍的ECS部署方式更倾向于开发、测试等环境下的单机部署。K8S的代码配置回到项目本身,代码仓库中的./kompose/文件夹下有多个yaml文件。可以看出,每个服务都有两个配置文件(*-deployment.yaml与*-service.yaml)共同进行配置。此处以db-deployment.yaml为例,对yaml配置仅作简短的介绍,帮助大家理解配置内容。随着集群版本和产品能力的更迭,也有很多配置信息将发生变化。所以在实践当中,需要调整 yaml 文件配置 。• apiVersion:此处值为apps/v1,这个版本号需要根据安装的K8S版本和资源类型进行变化。目前实践中对应v1.19版本的K8S集群。• kind:此处创建的是Deployment,根据实际情况,此处资源类型可以是Pod、Job、Ingress、Service等。如:在*-service.yaml文件中,创建的资源类型则是Service。• metadata:包含Deployment的一些meta信息。其中,annotations的含义是注解。• spec:你所期望的该对象的状态。包括replicas、selector、containers等Kubernetes需要的参数。其中,containers定义了该deployment使用的镜像:docker-server/docker-org/postgres:9.4。在上篇文章中提到过,这里的docker-server、docker-org都会在构建任务中替换为实际镜像对应的镜像地址和组织。strategy、restartPolicy等字段共同构成了容器失败时重启的策略。在*-service.yaml当中,主体内容与*-deployment.yaml相差也不算大,主要差异集中于spec这部分。*-service.yaml对应的spec主要是定义了集群内访问的方式,使各个服务之间可以互相访问。可以看出,*-deployment.yaml 与*-service.yaml共同定义了一个服务*。*-deployment.yaml主要定义了该服务的镜像源,或者说工作负载是什么。而*-service.yaml则定义了该服务访问方式。K8S的部署配置在编译构建环节,主体还是制作镜像上传到SWR镜像仓库,与上篇文章的没有区别。相关的配置文件也通过构建任务上传到软件发布库了,所以这里就不赘述了。镜像、配置和集群资源都准备妥当以后,就是使用K8S部署的环节了。代理机配置我们在HE2E实践中采用的是代理机的部署方式,将集群中的一个节点作为代理机进行授信、部署。所以在实践中我们从集群下载Kubectl配置文件并配置到节点主机当中(见《配置 Kubectl 》)。通过配置Kubectl的操作,我们就可以在节点主机上执行命令进而影响整个CCE集群。CCE部署任务HE2E实践中,phoenix-cd-cce是我们所需执行的部署任务。该任务将配置文件传输到目标主机,即代理机、集群节点。而后,通过执行shell命令启动Kubenetes。kubectl delete secret regcredkubectl create secret docker-registry regcred --docker-server=${docker-server} --docker-username=${docker-username} --docker-password=${docker-password} --docker-email=***@***.cn kubectl delete -f /root/phoenix-sample-deploy/kompose/kubectl apply -f /root/phoenix-sample-deploy/kompose/• 这里先是删除原有的secret,这一步主要是为了防止由于使用临时登录命令变化而导致secret错误引发的任务执行失败。• 接着,创建新的secret。包含docker-server、docker-username、docker-password等信息。• 按配置文件(/root/phoenix-sample-deploy/kompose/)删除资源。• 按配置文件(/root/phoenix-sample-deploy/kompose/)对资源进行配置。成功执行该部署任务后,可以在CCE集群中看到五个工作负载已经处于“运行中”的状态。不过目前还需要设置“节点访问”才能正常访问。所以在后续实践中对工作负载vote和result手动添加访问方式。节点访问设置完毕后,即可访问项目的用户端与管理端了。K8S的模板部署方式理论上,讲到现在,HE2E实践中的K8S部署就已经讲完了。但是,笔者猜到,肯定有很多人不喜欢这种通过代理机部署集群的方式。不过没关系,下面我就来介绍DevCloud当中的Kubernetes模板部署。新建模板时,现在可以选择模板:Kubernetes部署。进入模板以后,可以选择集群类型、区域、命名空间、部署方式等信息。由于本项目通过10个yaml文件共同配置,所以需要添加相同的“Kubernetes部署”步骤共计10个,每个步骤都对应一个yaml文件。而由于我们在代码仓库中的配置并非我们最终部署时所需的配置(经过编译构建修改docker-server等参数),所以我们需要每个步骤都设置软件发布库中对应的yaml文件。此时,我们会发现,我们原本的构建任务是将所有yaml文件进行了打包压缩后才上传的,没有办法直接选中。所以,我们可以再次创建一个构建任务或者在原有构建任务上进行修改,以使软件发布库中存放有所有的yaml文件。构建任务上传步骤的配置参考:(上传所有yaml文件而非打包后上传)完成以上配置以后,执行Kubernetes部署模板任务,即可将服务部署至选定的CCE集群当中。此时再添加节点访问方式即可访问用户端与管理端。当然,我们也可以将节点访问也写入yaml文件中,实现进一步的一键部署。这里就暂且留作一个小思考题,感兴趣的小伙伴可以自己尝试一下,将节点访问写入yaml当中。结语本篇文章一面介绍了HE2E实践中的CCE部署方式,一面又介绍了该实践中未提到的Kubernetes模板部署。两者的主要区别是“CCE部署”是通过代理机控制集群进行K8S部署;Kubernetes模板部署则是直接在集群中部署。此外,本文也对项目中关于K8S的配置进行了一定程度的解析。希望可以帮助小伙伴们理解K8S、HE2E,祝大家在技术成长的道路上越走越远。感谢小伙伴们的阅读。如果觉得还不错,不妨点个赞再走~此文由DevSecOps专家服务团队出品,前往 专家服务 ,获取更多DevSecOps工程方法、工具平台、最佳实践等干货。
  • [技术干货] 华为云云容器引擎CCE使用入门【与云原生的故事】【转载】
    一、创建Kubernetes集群1、创建集群1.1、登录CCE控制台https://console.huaweicloud.com/cce/1.2、创建CCE集群登录CCE控制台后会看见一个引导页面,请在CCE集群下单击“创建”按钮。1.3、配置集群参数参数说明如下:参数参数说明集群名称新建集群的名称。集群名称长度范围为4-128个字符,以小写字母开头,由小写字母、数字、中划线(-)组成,且不能以中划线(-)结尾。集群版本集群版本。建议选择最新的版本,对应Kubernetes社区基线版本。集群规模当前集群可以管理的最大Node节点规模。若选择50节点,表示当前集群最多可管理50个Node节点。高可用默认选择“是”。网络模型默认即可。虚拟私有云新建集群所在的虚拟私有云。若没有可选虚拟私有云,单击“新建虚拟私有云”进行创建,完成创建后单击刷新按钮。容器网段按默认配置即可。服务网段按默认配置即可。1.4、提交在右侧界面中会显示集群的资源清单,选择计费模式后,单击“提交”按钮,等待集群创建成功。创建成功后在集群管理下会显示一个运行中的集群,且集群节点数量为0。2、创建节点集群创建成功后,您还需要在集群中创建运行工作负载的节点。2.1、参数配置登录CCE控制台,单击创建的集群,进入集群控制台,在左侧菜单栏选择节点管理,单击右上角“创建节点”,在弹出的页面中配置节点的参数。参数说明如下:参数参数说明计算配置可用区默认即可。节点类型选择“虚拟机节点”。节点规格根据业务需求选择相应的节点规格。操作系统请选择节点对应的操作系统。节点名称自定义节点名称。登录方式支持密码和密钥对两种方式“密码”方式:用户名默认为“root”,请输入登录节点的密码,并确认密码。“密钥对”方式:在选项框中选择用于登录本节点的密钥对,并单击勾选确认信息。密钥对用于远程登录节点时的身份认证。若没有密钥对,可单击选项框右侧的“创建密钥对”来新建。存储配置系统盘按您的业务需求选择,缺省值为50GB。数据盘按您的业务需求选择,缺省值为100GB。网络配置虚拟私有云使用默认,即创建集群时选择的子网。节点子网选择节点所在的子网。2.2、规格确认在页面最下方选择节点的数量和计费模式,单击“下一步: 规格确认”。2.3、提交查看节点规格无误后,阅读页面上的使用说明,勾选“我已阅读并知晓上述使用说明”,单击“提交”按钮,等待节点创建成功,创建成功后在节点管理下会显示一个运行中的节点。二、镜像创建无状态工作负载(Nginx)1、前提条件您需要创建一个至少包含一个节点的集群,且该节点已绑定弹性公网IP,集群是运行工作负载的逻辑分组,包含一组云服务器资源,每台云服务器即集群中的一个节点。2、Nginx应用概述Nginx是一款轻量级的Web服务器,您可通过CCE快速搭建nginx web服务器。博主这里以选择“开源镜像中心”的方式创建应用为例,来创建一个Nginx工作负载。3、操作步骤3.1、镜像创建登录CCE控制台,单击集群进入集群控制台,在左侧菜单栏选择“工作负载”,单击右上角“镜像创建”。3.2、参数配置填写以下参数,其它保持默认。(1)基本参数配置参数参数说明负载类型选择无状态负载。负载名称nginx。实例数量设置为1。容器配置在基本信息中单击“选择镜像”,在弹出的窗口中选择“镜像中心”,并搜索“nginx”,选择nginx镜像。(2)服务配置单击服务配置下的加号,创建服务(Service),用于从外部访问负载,配置参数如下:参数参数说明Service名称输入应用发布的可被外部访问的名称,设置为:nginx。访问类型选择“负载均衡 ( LoadBalancer )”。服务亲和保持默认。负载均衡器如果已有负载均衡(ELB)实例,可以选择已有ELB,如果没有可单击“创建负载均衡器”,在ELB控制台创建一个公网类型负载均衡器。端口配置对外协议:TCP。服务端口:设置为8080,该端口号将映射到容器端口。容器端口:容器中应用启动监听的端口,nginx镜像请设置为80,其他应用容器端口和应用本身的端口一致。3.3、创建工作负载单击右下角“创建工作负载”,等待工作负载创建成功。创建成功后在无状态负载下会显示一个运行中的工作负载。4、访问Nginx(1)获取Nginx的外部访问地址单击Nginx工作负载名称,进入工作负载详情页。在访问方式页签下可以看到nginx的IP地址,其中负载均衡IP就是外部访问地址,如图所示:(2)在浏览器中输入“外部访问地址”,即可成功访问应用,如下图所示:【与云原生的故事】有奖征文火热进行中:https://bbs.huaweicloud.com/blogs/345260链接:https://bbs.huaweicloud.com/blogs/351622
  • [技术干货] Devcloud持续集成篇之-参数化Kubernetes部署
    Kubernetes的主要功能是容器编排,是指确保所有容器都按照计划运行在物理机或虚拟机上。这些容器在部署环境和集群配置的约束下被打包执行大量工作负载。此外,Kubernetes必须密切关注所有运行中的容器,替换运行中止,无响应或其他非正常状态的容器。               软件开发平台(DevCloud)是面向开发者提供的一站式云端DevOps平台,即开即用,随时随地在云端交付软件全生命周期,覆盖需求下发、代码提交、代码检查、代码编译、验证、部署、发布,打通软件交付的完整路径,提供软件研发流程的端到端支持,全面支撑落地DevOps。        本文着重介绍各位技术大咖在进行devcloud->部署->Kubernetes部署时,如何高效正确打通全流程参数化~ 废话不多说,下面开始手把手教学(*^▽^*)!!       首先我们介绍一下为什么要参数化~ 在敏捷开发,小步快跑的过程中,我们通过提交代码,执行各种各样的构建任务,编译打包镜像并上传到我们的华为云容器镜像服务SWR中,那么我们如何方便的管理我们的镜像呢?如果把镜像名称写成固定值,那么每次上传都会把旧版本覆盖掉,不利于我们的回滚和版本管理;而且我们的Kubernetes部署需要识别到yml文件的内容变动,部署后才会触发镜像更新!基于以上几点,参数化这个功能真是显得格外重要~ 下面我们开始图文并茂,直接上干货!
  • [技术干货] Devcloud持续集成篇之-参数化Kubernetes部署
    前文:        Kubernetes的主要功能是容器编排,是指确保所有容器都按照计划运行在物理机或虚拟机上。这些容器在部署环境和集群配置的约束下被打包执行大量工作负载。此外,Kubernetes必须密切关注所有运行中的容器,替换运行中止,无响应或其他非正常状态的容器。                软件开发平台(DevCloud)是面向开发者提供的一站式云端DevOps平台,即开即用,随时随地在云端交付软件全生命周期,覆盖需求下发、代码提交、代码检查、代码编译、验证、部署、发布,打通软件交付的完整路径,提供软件研发流程的端到端支持,全面支撑落地DevOps。        本文着重介绍各位技术大咖在进行devcloud->部署->Kubernetes部署时,如何高效正确打通全流程参数化~ 废话不多说,下面开始手把手教学(*^▽^*)!!       首先我们介绍一下为什么要参数化~ 在敏捷开发,小步快跑的过程中,我们通过提交代码,执行各种各样的构建任务,编译打包镜像并上传到我们的华为云容器镜像服务SWR中,那么我们如何方便的管理我们的镜像呢?如果把镜像名称写成固定值,那么每次上传都会把旧版本覆盖掉,不利于我们的回滚和版本管理;而且我们的Kubernetes部署需要识别到yml文件的内容变动,部署后才会触发镜像更新!基于以上几点,参数化这个功能真是显得格外重要~ 下面我们开始图文并茂,直接上干货!持续集成嘛,提交代码的目的是为了打包编译,然后部署到目标集群,我们通过编译构建任务,新建步骤“制作镜像并推送到SWR仓库”,实现这个目的:我们试着构建一下~ 构建成功后,可以去容器镜像服务SWR里确认一下成果~!然后我们去部署服务里,新建kubernetes部署,按下图进行配置~同样~:我们在部署任务的参数设置中,也像构建那样,新建参数。接下来这步是重点哦,我们去代码仓库中的yml文件里,通过{{}}引用我们部署任务里的参数“version”下图是样例:接下来,我们通过流水线服务,把上述任务串起来~ 然后我们把流水线中的这个参数类型改为自增长,勾选"运行时设置",这样我们只需要首次执行流水线任务的时候给它赋予一个初始值,以后就会根据这个初始值进行自增长接下来,我们保存并执行一下这个流水线任务~(可以手动执行,也可以通过提交代码触发执行),然后静静的等待任务结束哎呦,部署成功了~我们看下执行参数是否成功取到了自增长的参数值。看起来没什么问题~ 因为我太菜~已经测试了4次OK!大功告成,最后我们去CCE集群的工作负载里检验一下最终成果!怎么样大咖们? 大家都学废,啊呸,大家都学会了嘛~ 请奔走相告~~
总条数:101 到第
上滑加载中