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')
  }
}

  

 

posted @ 2023-10-16 18:29  我的天啊~  阅读(9287)  评论(0编辑  收藏  举报