k8s是什么?
一. 概述
1、k8s是什么?
Kubernetes(简称k8s)是一个开源的容器编排和管理系统,由Google开发并维护。它可以自动化地部署、扩展和管理容器化的应用程序,使得这些应用程序可以更加高效、可靠、可伸缩地运行。
Kubernetes的设计目标是使得应用程序的部署和管理变得更加简单、可靠和可扩展,从而帮助开发人员和运维人员更好地管理和运行容器化的应用程序。
2、为什么称k8s是云原生核心技术?
k8s使得【应用程序】可以更好地适应【云环境】的要求,实现高效、可靠、可扩展的部署和管理。
云原生(Cloud-Native)是一种软件开发和部署的方法论,旨在最大程度地利用云计算的优势,提高应用程序的可扩展性、弹性和可靠性。 云计算可以分为三种服务模式:基础设施即服务(IaaS)【阿里云】、平台即服务(PaaS)和软件即服务(SaaS)【crm】。
3、k8s和docker的关系?
Docker是一种常用的容器化技术。
Kubernetes提供了一个容器运行时接口(Container Runtime Interface,CRI),符合CRI规范的容器运行时,都可以被k8s管理和编排。如rkt、containerd等。
Docker 是目前最流行的 Linux 容器方案,所以Docker的containerd是Kubernetes中最常用的容器运行时。
k8s vs docker-swarm
k8s 的特点:自我修复 、弹性伸缩、 自动部署和回滚、 服务发现和负载均衡 、机密和配置管理 、存储编排 、批处理。
swarm:随 Docker 引擎一起发布,无需额外安装,配置简单。
Kubernetes在容器编排和管理方面更加强大和灵活,拥有更多的功能和扩展性:
弹性伸缩: swarm只有副本增加,k8s支持cpu、内存监控拓展
自我修复:swarm监控节点状态,k8s定义存活检查
调度策略: swarm只支持轮询问部署到可用节点上,k8s有污点、亲和性等策略
存储方面:swarm只是简单volume挂载,k8s有动态制备器、pv、pvc等高级特性
等等
4、学习k8s需要会docker吗?
需要了解docker打包,上传命令。其他命令基本上被k8s接管,使用时几乎感知不到docker。
二、k8s如何使用
以下仅供扫盲,展示大概流程,不是实操!。
1、k8s环境搭建
先安装docker、docker-compose后。
再安装k8s组件:yum install -y kubelet-1.23.6 kubeadm-1.23.6 kubectl-1.23.6
# kubelet运行在每个节点上,负责管理节点上的容器和Pod。kubeadmin是Kubernetes集群的初始化工具,它负责初始化一个全新的集群。kubectl是Kubernetes的命令行工具,用于与集群进行交互。
kubeadm init \ # 创建一个集群,此服务器就是master节点 --apiserver-advertise-address=172.16.200.102 \ --image-repository registry.aliyuncs.com/google_containers \ --kubernetes-version v1.23.6 \ --service-cidr=10.96.0.0/12 \ # svc的虚拟ip范围,(/12 表示前12位是网络地址,后面的20位是主机地址。这个范围包含了从10.96.0.0到10.111.255.255的所有IP地址) --pod-network-cidr=10.244.0.0/16 # pod的虚拟ip范围,(/16 表示前16位是网络地址,包含从10.244.0.0到10.244.255.255的所有IP地址)
<br/> kubeadm join 172.16.200.102:6443 --token w6remf.xsksps2pcllkiapz \ --discovery-token-ca-cert-hash sha256:7bf22fbc5801ced7019804cb064901b06d0264152b3d87dda9853704a54a168a # 加入节点,此服务器为node节点
<br/> kubectl apply -f calico.yaml # 安装cni网络插件 在Kubernetes中,CNI(Container Network Interface)网络是用于管理容器网络的一种标准化接口。 CNI定义了一组规范和API,用于创建、配置和管理容器网络。它允许不同的网络插件(如Calico、Flannel、Weave等)与Kubernetes集群集成,提供容器之间的通信和网络隔离。
route -n #查看路由情况,可以看出大概通信端倪
2、服务重启
当修改配置后,可能需要重启服务
systemctl daemon-reload #会重新加载/etc/systemd/system目录下的所有配置文件
systemctl restart docker #重启docker
systemctl restart kubelet #重启kubelet
核心组件
1. `calico-kube-controllers-74dbdc644f-k5wh2`:该Pod运行Calico Kubernetes控制器,负责管理Calico网络策略规则。
2. `calico-node-b89js:这些Pod运行Calico节点守护程序,负责在每个Kubernetes节点上执行Calico网络策略。
3. `coredns-6d8c4cb4d-48sg9`:这些Pod运行CoreDNS DNS服务器,为Kubernetes服务提供名称解析。
4. `etcd-k8s-master`:该Pod运行etcd分布式键值存储,Kubernetes使用它来存储配置数据。
5. `kube-apiserver-k8s-master`:该Pod运行Kubernetes API服务器,为管理Kubernetes资源提供RESTful API。
6. `kube-controller-manager-k8s-master`:该Pod运行Kubernetes控制器管理器,负责管理Kubernetes控制器。
7. `kube-proxy-h9crx`:这些Pod运行Kubernetes网络代理,负责将网络流量转发到适当的Kubernetes Pod。
8. `kube-scheduler-k8s-master`:该Pod运行Kubernetes调度器,负责将Kubernetes Pod调度到Kubernetes节点上。
9. `metrics-server-55db4f88bc-fqhfb`:该Pod运行Kubernetes指标服务器,收集Kubernetes Pod和节点的资源使用情况指标。
10. `snapshot-controller-0`:该Pod运行Kubernetes快照控制器,负责管理卷快照操作。
3、在k8s中常用操作
常用可操作的资源有(在k8s中一切皆资源,如linux一切皆文件一样):
pods # pod是最小的部署单元 po (简写) deployments # pods编排的资源对象。无状态 deploy (简写)
statefulset # pods编排的资源对象,有状态
sts (简写) services # Pods访问策略的资源对象,svc都会提供一个统一的入口点,使得我们可以通过svc访问到任何一个Pod。svc还可以提供负载均衡、服务发现、会话保持等功能,简单来说就是pod间网络通信 svc (简写) namespace # 命名空间资源对象 ns (简写) nodes # 节点资源对象 no (简写) 格式化输出指令 输出 json 格式:-o json 仅打印资源名称:-o name 以纯文本格式输出所有信息:-o wide 输出 yaml 格式:-o yaml
kubectl get nodes # 查看全部节点状态
kubectl get cs # 查看组件状态componentstatus
kubectl get po -o wide # 查看全部的pod,-n 可指定命名空间
kubectl get sc # 查看全部存储类storage class
kubectl get nodes --show-labels # 显示node的全部标签
kubectl label node k8s-node1 ingress=true # 给k8s-node1节点增加了ingress=true的标签,标签选择器使用
kubectl describe no k8s-master # 展示node详细信息, 可以查看到taint污点,kubectl 污点、亲和力的时候用
kubectl taint node k8s-master key=value:NoSchedule # 增加污点
kubectl taint node k8s-master key=value:NoSchedule- # 删除污点
kubectl get svc # 查看服务service
kubectl get ep # 查看endpoints
kubectl describe po redis -n kube-devops # 查看描述信息
kubectl logs -f redis -n kube-devops # 查看容器日志
kubectl exec -it nginx-85b98978db-7s7hh -- bash #进入pod的主容器
kubectl create ns redis # 创建一个名为redis的命名空间,[不建议直接创建,建议使用文件创建 -f xx.yaml]
kubectl create deployment nginx --image=nginx # 创建一个部署资源,然后启动pod[不建议直接创建,建议使用文件创建 -f xx.yaml]
kubectl annotate deployment nginx kubernetes.io/change-cause="your change cause message" # 增加版本说明
kubectl get rs --show-labels #查看副本数
kubectl rollout history deploy/nginx #查看历史版本
kubectl rollout history deploy/nginx --revision=2 #查看此版本的变更情况
kubectl rollout undo eployment/nginx --to-revision=2 # 回滚指定版本
helm install redis ./redis/ -n kube-devops # 通过helm安装redis,在kube-devops命名空间里 Helm是一个Kubernetes的包管理工具,它允许用户轻松地安装、升级和管理Kubernetes应用程序。 其模版文件称为Chart。 通过修改Chart.yaml和values.yaml文件,可以自定义应用程序的配置选项,然后使用Helm命令轻松将Chart部署到Kubernetes集群中。
可以类比为centos中的yum , ubuntu中的apt
4、具体示例
- kubectl create -f nginx-deploy.yaml # 部署一个nginx,nginx-deploy.yaml 原文如下:
apiVersion: apps/v1 # deployment api 版本 kind: Deployment # 资源类型为 deployment metadata: # 元信息 labels: # 标签 app: nginx-deploy # 具体的 key: value 配置形式 name: nginx-deploy # deployment 的名字 namespace: default # 所在的命名空间 spec: replicas: 1 # 期望副本数 revisionHistoryLimit: 10 # 进行滚动更新后,保留的历史版本数 selector: # 选择器,用于找到匹配的 RS matchLabels: # 按照标签匹配 app: nginx-deploy # 匹配的标签key/value strategy: # 更新策略 rollingUpdate: # 滚动更新配置 maxSurge: 25% # 进行滚动更新时,最多超过期望副本数的个数/比例 maxUnavailable: 25% # 进行滚动更新时,最多可以同时不可用的个数 type: RollingUpdate # 更新类型,采用滚动更新 template: # pod 模板 metadata: # pod 的元信息 labels: # pod 的标签 app: nginx-deploy spec: # pod 期望信息 containers: # pod 的容器 - image: nginx:1.7.9 # 镜像 imagePullPolicy: IfNotPresent # 拉取策略 name: nginx # 容器名称 resources: limits: cpu: 200m memory: 128Mi requests: # 最小部署资源,有1/10的cpu,和128m内存 cpu: 100m # 一个cpu是1000m memory: 128Mi restartPolicy: Always # 重启策略,自动重启 terminationGracePeriodSeconds: 30 # 删除操作最多宽限多长时间
- kubectl create -f nginx-svc.yaml # 部署一个nginx网络服务,nginx-svc.yaml 原文如下:
apiVersion: v1 kind: Service metadata: name: nginx-svc labels: app: nginx spec: selector: app: nginx-deploy ports: - port: 80 targetPort: 80 nodePort: 30338 #到所有 node 的 32000 端口上 name: web type: NodePort
这样就可以通过访问主机ip+端口,外部访问nginx: http://172.16.200.102:30338
同时通过访问svc名称+端口,内部访问nginx: http://nginx-svc:80 ,微服务一般都是这样进行内部通信
非同命名空间,还需要加命名空间:http://nginx-svc.default:80
svc一般用于内部通信(东西网络),如果对外暴露(南北网络)一般还是ingress插件
Ingress是一个API对象,用于管理入站网络流量的访问。它允许对Kubernetes集群中的多个服务进行统一的访问和路由,可以通过不同的规则将流量路由到不同的服务中。 Kubernetes社区中有多个Ingress控制器可供选择,需要单独安装!
详情:https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress-controllers/ # 以安装 ingress-nginx控制器插件为例 helm install ingress-nginx ./ingress-nginx -n ingress-nginx
安装好ingress控制器插件后,再创建ingress资源
- kubectl create -f ingress-svc.yaml # 部署一个南北流量网络,ingress-svc.yaml 原文如下:
apiVersion: networking.k8s.io/v1 kind: Ingress # 资源类型为 Ingress metadata: name: wolfcode-nginx-ingress annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: # ingress 规则配置,可以配置多个 - host: "*.pzhang.cn" # 域名配置,可以使用通配符 * http: paths: # 相当于 nginx 的 location 配置,可以配置多个 - pathType: Prefix # 路径类型,Prefix:以 / 作为分隔符来进行前缀匹配 backend: service: name: nginx-svc # 代理到哪个 service port: number: 80 # service 的端口 path: / # 等价于 nginx 中的 location 的路径前缀匹配
然后外部就可以访问了:http://nginx.pzhang.cn/ ,
注意自己配host,ip指向Ingress控制器安装的目标机:172.16.200.98 nginx.pzhang.cn
三. devops(CI/CD)
1、名词解释
DevOps(Development和Operations的组合词):是指开发人员(Dev)和运维人员(Ops)之间的一种合作和协作文化,旨在加强软件开发和运维的整体效率和质量。
DevOps的目标是通过自动化、持续集成和持续交付等实践,实现开发和运维团队之间的无缝协作,以更快、更可靠地交付软件。
CI(Continuous Integration,持续集成)
CD(Continuous Delivery,持续交付)
CI/CD是DevOps实践的核心组成部分。通过持续集成和持续交付的实践,开发人员可以快速、频繁地集成和交付软件,而运维团队可以通过自动化的流程来管理和部署软件。
2、k8s可视化系统
支持k8s可视化的组件有很多,kubesphere就是其中之一,它功能强大。大大的方便运维。
安装过程如下:
# 安装资源 kubectl apply -f https://github.com/kubesphere/ks-installer/releases/download/v3.3.1/kubesphere-installer.yaml kubectl apply -f https://github.com/kubesphere/ks-installer/releases/download/v3.3.1/cluster-configuration.yaml # 检查安装日志 kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l 'app in (ks-install, ks-installer)' -o jsonpath='{.items[0].metadata.name}') -f
在kubesphere中还可以开启devops功能, 有jenkis图标,证明devops已开启。开启后自动安装jenkins,并可以图形化设计cicd流程(待续)。
基于 Jenkins 的 KubeSphere DevOps 系统是专为 Kubernetes 中的 CI/CD 工作流设计的,它提供了一站式的解决方案,帮助开发和运维团队用非常简单的方式构建、测试和发布应用到 Kubernetes
3、CICD一般工作流程图
4、基于jenkins的CICD流程驱动
除了kubesphere图形界面控制台设计构建流程,在已有的外部jenkins也可以进行流程控制。
jenkinsfile内容包括:
- stage1: checkout 代码
- stage2:unit test 单元测试
- stage3: sonaqube代码检查
- stage4: mvn package & dockerfile build 构建镜像
- stage5: 推送镜像到harbor
- stage6: kubectl apply -f deployment.yml 运行
jenkins全文如下:
pipeline { agent { kubernetes { label 'maven' } } stages { stage('checkout scm') { agent none steps { git(url: 'http://172.16.200.102:28080/root/shop-flashsale.git', credentialsId: 'gitlab-user-pass', changelog: true, poll: false, branch: "$BRANCH_NAME") } } stage('unit test') { agent none steps { container('maven') { sh '''cd ${SERVICE} mvn clean test''' } } } stage('sonarqube analysis') { agent none steps { withCredentials([string(credentialsId : 'sonarqube' ,variable : 'SONAR_TOKEN' ,)]) { withSonarQubeEnv('sonar') { container('maven') { sh '''service_name=${SERVICE#*/} service_name=${service_name#*/} cd ${SERVICE} mvn sonar:sonar -Dsonar.projectKey=${service_name} echo "mvn sonar:sonar -Dsonar.projectKey=${service_name}"''' } } } timeout(time: 1, unit: 'HOURS') { waitForQualityGate true } } } stage('build & push') { agent none steps { withCredentials([usernamePassword(credentialsId : 'harbor-user-pass' ,passwordVariable : 'DOCKER_PASSWORD' ,usernameVariable : 'DOCKER_USERNAME' ,)]) { container('maven') { sh '''cd ${SERVICE} mvn clean package -DskipTests cd ${WORKSPACE} chmod -R 777 deploy/copy.sh && deploy/copy.sh''' sh '''echo "${DOCKER_PASSWORD}" | docker login ${REGISTRY} -u "${DOCKER_USERNAME}" --password-stdin service_name=${SERVICE#*/} service_name=${service_name#*/} cd deploy/${service_name}/build docker build -f Dockerfile -t ${REGISTRY}/${DOCKERHUB_NAMESPACE}/${service_name}:SNAPSHOT-$BUILD_NUMBER . docker push ${REGISTRY}/${DOCKERHUB_NAMESPACE}/${service_name}:SNAPSHOT-${BUILD_NUMBER}''' } } } } stage('push latest') { agent none steps { container('maven') { sh '''service_name=${SERVICE#*/} service_name=${service_name#*/} cd deploy/${service_name}/build docker tag ${REGISTRY}/${DOCKERHUB_NAMESPACE}/${service_name}:SNAPSHOT-${BUILD_NUMBER} ${REGISTRY}/${DOCKERHUB_NAMESPACE}/${service_name}:latest docker push ${REGISTRY}/${DOCKERHUB_NAMESPACE}/${service_name}:latest ''' } } } stage('deploy to dev') { agent none steps { input(id: 'deploy-to-dev', message: 'deploy to dev?') container('maven') { withCredentials([kubeconfigContent(credentialsId : 'admin-kubeconfig' ,variable : 'ADMIN_KUBECONFIG' ,)]) { sh ''' service_name=${SERVICE#*/} service_name=${service_name#*/} cd deploy/${service_name} sed -i\'\' "s#REGISTRY#${REGISTRY}#" deployment.yaml sed -i\'\' "s#DOCKERHUB_NAMESPACE#${DOCKERHUB_NAMESPACE}#" deployment.yaml sed -i\'\' "s#APP_NAME#${service_name}#" deployment.yaml sed -i\'\' "s#BUILD_NUMBER#${BUILD_NUMBER}#" deployment.yaml sed -i\'\' "s#REPLICAS#${REPLICAS}#" deployment.yaml mkdir ~/.kube echo "$ADMIN_KUBECONFIG" > ~/.kube/config if [ ${service_name} != "frontend-server" ]; then kubectl create cm ${service_name}-yml --dry-run=\'client\' -oyaml --from-file=build/target/bootstrap.yml -n ks-shop-dev > ${service_name}-configmap.yml fi kubectl apply -f .''' } } } } stage('push with tag') { agent none when { expression { return params.TAG_NAME =~ /v.*/ } } steps { input(id: 'release-image-with-tag', message: 'release image with tag?') withCredentials([usernamePassword(credentialsId : 'gitlab-user-pass' ,passwordVariable : 'GIT_PASSWORD' ,usernameVariable : 'GIT_USERNAME' ,)]) { sh 'git config --global user.email "liugang@wolfcode.cn" ' sh 'git config --global user.name "xiaoliu" ' sh 'git tag -a ${TAG_NAME} -m "${TAG_NAME}" ' sh 'git push http://${GIT_USERNAME}:${GIT_PASSWORD}@${GIT_REPO_URL}/${GIT_ACCOUNT}/${APP_NAME}.git --tags --ipv4' } sh ''' service_name=${SERVICE#*/} service_name=${service_name#*/} docker tag ${REGISTRY}/${DOCKERHUB_NAMESPACE}/${service_name}:SNAPSHOT-${BUILD_NUMBER} ${REGISTRY}/${DOCKERHUB_NAMESPACE}/${service_name}:${TAG_NAME} docker push ${REGISTRY}/${DOCKERHUB_NAMESPACE}/${service_name}:${TAG_NAME} ''' } } stage('deploy to production') { agent none when { expression { return params.TAG_NAME =~ /v.*/ } } steps { input(id: 'deploy-to-production', message: 'deploy to production?') container('maven') { withCredentials([kubeconfigContent(credentialsId : 'admin-kubeconfig' ,variable : 'ADMIN_KUBECONFIG' ,)]) { sh ''' service_name=${SERVICE#*/} service_name=${service_name#*/} cd deploy/${service_name}/prod sed -i\'\' "s#REGISTRY#${REGISTRY}#" deployment.yaml sed -i\'\' "s#DOCKERHUB_NAMESPACE#${DOCKERHUB_NAMESPACE}#" deployment.yaml sed -i\'\' "s#APP_NAME#${service_name}#" deployment.yaml sed -i\'\' "s#BUILD_NUMBER#${BUILD_NUMBER}#" deployment.yaml sed -i\'\' "s#REPLICAS#${REPLICAS}#" deployment.yaml mkdir ~/.kube echo "$ADMIN_KUBECONFIG" > ~/.kube/config if [ ${service_name} != "frontend-server" ]; then kubectl create cm ${service_name}-yml --dry-run=\'client\' -oyaml --from-file=build/target/bootstrap.yml -n ks-shop-flashsale > ${service_name}-configmap.yml fi kubectl apply -f . ''' } } } } } environment { APP_NAME = 'shop-flashsale' DOCKER_CREDENTIAL_ID = 'harbor-user-pass' REGISTRY = '192.168.113.122:8858' GIT_REPO_URL = '172.16.200.102:28080' GIT_CREDENTIAL_ID = 'git-user-pass' GIT_ACCOUNT = 'root' SONAR_CREDENTIAL_ID = 'sonarqube-token' KUBECONFIG_CREDENTIAL_ID = '546163de-4d55-40b9-9035-83b51d91260b' } parameters { choice(name: 'SERVICE', choices: ['frontend-server', 'shop-parent/api-gateway', 'shop-parent/shop-uaa', 'shop-parent/shop-provider/product-server', 'shop-parent/shop-provider/flashsale-server'], description: '请选择要部署的服务') choice(name: 'DOCKERHUB_NAMESPACE', choices: ['snapshots', 'releases'], description: '请选择部署到哪个镜像仓库') choice(name: 'REPLICAS', choices: ['1', '3', '5', '7'], description: '请选择构建后的副本数') string(name: 'BRANCH_NAME', defaultValue: 'master', description: '请输入要构建的分支名称') string(name: 'TAG_NAME', defaultValue: 'snapshot', description: '部署版本:必须以 v 开头,例如:v1、v1.0.0') } }