美文网首页
容器化技术(No.2) -- Kubernetes 基础

容器化技术(No.2) -- Kubernetes 基础

作者: IrvinX | 来源:发表于2020-05-01 22:20 被阅读0次

    前言

    今天的分享主要有以下几个目标:

    • 了解什么是 Kubernetes, 架构组成及核心概念
    • 可以通过 kubeadm 独立搭建完整的集群
    • 尝试使用 kubectl 命令操作集群
    • 学习使用 YAML 编排简单任务

    Docker 回顾

    • 什么是 Docker?
    - 打包代码及其所有依赖项的软件的标准单元, 本质上是宿主机上的一个进程;
    - 通过 namespace 实现了资源隔离, 通过 cgroups 实现了资源限制, 通过 copy-on-write 机制实现了高效的文件操作
    - 与虚拟机相比, Docker 启动速度更快, 性能接近原生 (虚拟机损失 5% 左右), 资源使用更少
    

    容器化技术(No.1) -- Docker 基础

    • 思考:
    • 什么是 Kubernetes
    • 为什么要用 Kubernetes
    • Kubernetes 架构组成
    • Kubernetes 基本概念

    Kubernetes

    • Kubernetes 是 Google 在 2014 年开源的一个容器集群管理系统, 简称 K8S.
    • Kubernetes 用于容器化应用程序的部署, 扩展和管理, 目标是让部署容器化应用简单高效.

    官方网站:http://www.kubernetes.io

    技术架构及核心概念

    技术架构

    Kubernetes-Arch.png

    Master

    • kube-apiserver

    Kubernetes API, 集群的统一入口, 通过 api server 控制着这些资源的访问权限,通过使用暴露给外部用户REST API接口执行对Kubernetes资源的CRUD操作, 处理后再提交给 Etcd 存储.

    • kube-controller-manager

    处理集群中常规后台任务, 一个资源对应一个控制器, 而ControllerManager就是负责管理这些控制器的.

    • kube-scheduler

    根据调度算法为新创建的Pod选择一个Node节点, 可以任意部署,可以部署在同一个节点上,也可以部署在不同的节点上.

    • etcd

    分布式键值存储系统.用于保存集群状态数据, 比如Pod、Service等对象信息.

    Worker

    • kubelet

    kubelet是Master在Node节点上的Agent, 管理本机运行容器的生命周期, 比如创建容器、Pod挂载数据卷、下载secret、获取容器和节点状态等工作.kubelet将每个Pod转换成一组容器.

    • kube-proxy

    在Node节点上实现Pod网络代理, 维护网络规则和四层负载均衡工作. 主要作用就是负责 service 的实.

    • docker

    容器引擎, 运行容器.

    核心概念

    Pod

    • 最小部署单元
    • 一组容器的集合
    • 一个Pod中的容器共享网络命名空间
    • Pod是短暂的

    Controllers

    • Deployment : 无状态应用部署
    • StatefulSet: 有状态应用部署
    • DaemonSet : 确保所有 Node 运行相同的 Pod
    • Job : 一次性任务
    • Cronjob : 定时任务

    控制器是更高级层次对象, 用于部署和管理 Pod.

    Service

    • 防止 Pod 失联
    • 定义一组 Pod 的访问策略

    Label

    • 标签, 附加到某个资源上, 用于关联对象、查询和筛选

    Namespaces

    • 命名空间, 将对象逻辑上隔离

    基础实践

    部署方式

    官方提供三种部署方式:

    • minikube

    Minikube是一个工具,可以在本地快速运行一个单点的Kubernetes,仅用于尝试Kubernetes或日常开发的用户使用。
    部署地址:https://kubernetes.io/docs/setup/minikube

    • kubeadm

    Kubeadm也是一个工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。
    部署地址:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm

    • 二进制

    推荐,从官方下载发行版的二进制包,手动部署每个组件,组成Kubernetes集群。
    下载地址:https://github.com/kubernetes/kubernetes/releases

    部署集群

    kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具.

    这个工具能通过两条指令完成一个kubernetes集群的部署:

    # 创建一个 Master 节点
    $ kubeadm init
    
    # 将一个 Node 节点加入到当前集群中
    $ kubeadm join <Master节点的IP和端口 >
    
    安装要求

    在开始之前, 部署Kubernetes集群机器需要满足以下几个条件:

    • 一台或多台机器, 操作系统 CentOS7.x-86_x64
    • 硬件配置:>=2GB mem, >=2 core, >=30GB disk
    • 集群中所有机器之间网络互通
    • 可以访问外网, 需要拉取镜像
    • 禁止swap分区
    准备环境
    角色 IP
    k8s-master 192.168.0.10
    k8s-node1 192.168.0.11
    k8s-node2 192.168.0.12
    #关闭防火墙
    $ systemctl stop firewalld
    $ systemctl disable firewalld
    
    #关闭selinux
    $ sed -i 's/enforcing/disabled/' /etc/selinux/config  # 永久
    $ setenforce 0  # 临时
    
    #关闭swap
    $ swapoff -a  # 临时
    $ vim /etc/fstab  # 永久
    
    #设置主机名
    $ hostnamectl set-hostname <hostname>
    
    #在master添加hosts
    $ cat >> /etc/hosts << EOF
    192.168.0.1 k8s-master
    192.168.0.2 k8s-node1
    192.168.0.3 k8s-node2
    EOF
    
    #将桥接的IPv4流量传递到iptables的链
    $ cat > /etc/sysctl.d/k8s.conf << EOF
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    EOF
    $ sysctl --system  # 生效
    
    #时间同步
    $ yum install ntpdate -y
    $ ntpdate -u cn.ntp.org.cn
    
    所有节点安装Docker/kubeadm/kubelet

    Kubernetes 默认 CRI(容器运行时)为 Docker, 因此先安装 Docker.

    1、 安装Docker

    $ wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
    $ yum install -y docker-ce-18.09.9-3.el7 
    $ systemctl enable docker && systemctl start docker
    $ docker --version
    
    # cat > /etc/docker/daemon.json << EOF
    {
      "registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
    }
    EOF
    

    2、 添加阿里云 YUM 软件源

    $ 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
    

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

    $ yum install -y kubelet-1.16.2 kubeadm-1.16.2 kubectl-1.16.2
    $ systemctl enable kubelet
    
    部署 Kubernetes Master

    在192.168.0.10(Master)执行.

    $ kubeadm init \
      --apiserver-advertise-address=192.168.0.10 \
      --image-repository registry.aliyuncs.com/google_containers \
      --kubernetes-version v1.16.2 \
      --service-cidr=10.96.0.0/12 \
      --pod-network-cidr=10.244.0.0/16
    

    kubeadm 到底做了什么? 稍后说明.

    由于默认拉取镜像地址k8s.gcr.io国内无法访问, 这里指定阿里云镜像仓库地址.

    使用kubectl工具:

    mkdir -p $HOME/.kube
    sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config
    $ kubectl get nodes
    
    安装Pod网络插件(CNI)
    $ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
    

    确保能够访问到quay.io这个registery.

    加入Kubernetes Node

    在192.168.0.11/12(Worker)执行.

    向集群添加新节点, 执行在kubeadm init输出的kubeadm join命令:

    $ kubeadm join 192.168.0.10:6443 --token i1ofj9.ujm6xpc7sx4tmt1c \
        --discovery-token-ca-cert-hash sha256:7ce38ff560c14aa85e2ae1736c081019b9890c78aee86cd75c4ff1ef311d6aa9
    

    默认token有效期为24小时, 超时就需要重新创建token, 操作如下:

    # Master 节点执行
    $ kubeadm token create
    i1ofj9.ujm6xpc7sx4tmt1c
    $ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
    7ce38ff560c14aa85e2ae1736c081019b9890c78aee86cd75c4ff1ef311d6aa9
    # Worker 上执行
    $ kubeadm join 192.168.0.10:6443 --token i1ofj9.ujm6xpc7sx4tmt1c --discovery-token-ca-cert-hash sha256:7ce38ff560c14aa85e2ae1736c081019b9890c78aee86cd75c4ff1ef311d6aa9
    

    也可以通过如下命令直接获取

    $ kubeadm token create --print-join-command
    

    官方文档: https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-join

    测试kubernetes集群

    在Kubernetes集群中创建一个pod, 验证是否正常运行:

    $ kubectl create deployment nginx --image=nginx
    $ kubectl expose deployment nginx --port=80 --type=NodePort
    $ kubectl get pod,svc
    

    访问地址:http://NodeIP:Port

    部署 Dashboard
    $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml
    

    默认Dashboard只能集群内部访问, 修改Service为NodePort类型, 暴露到外部:

    kind: Service
    apiVersion: v1
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard
      namespace: kubernetes-dashboard
    spec:
      ports:
        - port: 443
          targetPort: 8443
      selector:
        k8s-app: kubernetes-dashboard
    

    访问地址:http://NodeIP:Port

    创建service account并绑定默认cluster-admin管理员集群角色:

    kubectl create serviceaccount dashboard-admin -n kube-system
    kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
    kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
    

    使用输出的token登录Dashboard.

    kubeadm init 到底做了些什么
    [root@Ali-irvin ~]# kubeadm init \
    >   --apiserver-advertise-address=192.168.0.10 \
    >   --image-repository registry.aliyuncs.com/google_containers \
    >   --kubernetes-version v1.16.2 \
    >   --service-cidr=10.96.0.0/12 \
    >   --pod-network-cidr=10.244.0.0/16
    [init] Using Kubernetes version: v1.16.
    # 1. 环境检查
    [preflight] Running pre-flight checks       
      [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
    # 2. 下载镜像
    [preflight] Pulling images required for setting up a Kubernetes cluster
    [preflight] This might take a minute or two, depending on the speed of your internet connection
    [preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
    # 3. 为 kubelet 创建配置文件并启动
    [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
    [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
    [kubelet-start] Activating the kubelet service
    # 4. 为apiserver、etcd生成https证书
    [certs] Using certificateDir folder "/etc/kubernetes/pki"
    [certs] Generating "ca" certificate and key
    [certs] Generating "apiserver" certificate and key
    [certs] apiserver serving cert is signed for DNS names [ali-irvin kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.0.10]
    [certs] Generating "apiserver-kubelet-client" certificate and key
    [certs] Generating "front-proxy-ca" certificate and key
    [certs] Generating "front-proxy-client" certificate and key
    [certs] Generating "etcd/ca" certificate and key
    [certs] Generating "etcd/server" certificate and key
    [certs] etcd/server serving cert is signed for DNS names [ali-irvin localhost] and IPs [192.168.0.10 127.0.0.1 ::1]
    [certs] Generating "etcd/peer" certificate and key
    [certs] etcd/peer serving cert is signed for DNS names [ali-irvin localhost] and IPs [192.168.0.10 127.0.0.1 ::1]
    [certs] Generating "etcd/healthcheck-client" certificate and key
    [certs] Generating "apiserver-etcd-client" certificate and key
    [certs] Generating "sa" key and public key
    # 5. 生成连接apiserver的kubeconfig文件
    [kubeconfig] Using kubeconfig folder "/etc/kubernetes"
    [kubeconfig] Writing "admin.conf" kubeconfig file
    [kubeconfig] Writing "kubelet.conf" kubeconfig file
    [kubeconfig] Writing "controller-manager.conf" kubeconfig file
    [kubeconfig] Writing "scheduler.conf" kubeconfig file
    # 6. 容器启动 master 组件
    [control-plane] Using manifest folder "/etc/kubernetes/manifests"
    [control-plane] Creating static Pod manifest for "kube-apiserver"
    [control-plane] Creating static Pod manifest for "kube-controller-manager"
    [control-plane] Creating static Pod manifest for "kube-scheduler"
    [etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
    [wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
    [apiclient] All control plane components are healthy after 18.002987 seconds
    # 7. 将涉及的配置文件存储到 configmap
    [upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
    [kubelet] Creating a ConfigMap "kubelet-config-1.16" in namespace kube-system with the configuration for the kubelets in the cluster
    [upload-certs] Skipping phase. Please see --upload-certs
    # 8. 设置 master 节点不可调度 Pod
    [mark-control-plane] Marking the node ali-irvin as control-plane by adding the label "node-role.kubernetes.io/master=''"
    [mark-control-plane] Marking the node ali-irvin as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
    # 9. 启用 bootstrap 自动为 kubelet 颁发证书
    [bootstrap-token] Using token: i1ofj9.ujm6xpc7sx4tmt1c
    [bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
    [bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
    [bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
    [bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
    [bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
    # 10. 安装插件:CoreDNS、kube-proxy
    [addons] Applied essential addon: CoreDNS
    [addons] Applied essential addon: kube-proxy
    
    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
    
    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.0.10:6443 --token i1ofj9.ujm6xpc7sx4tmt1c \
        --discovery-token-ca-cert-hash sha256:7ce38ff560c14aa85e2ae1736c081019b9890c78aee86cd75c4ff1ef311d6aa9
    [root@Ali-irvin ~]#
    
    1、检查系统环境是否满足,例如swap是否关闭、配置是否满足
    2、下载所需镜像,kubeadm config images pull
    3、为 kubelet 创建配置文件并启动
    4、为 apiserver、etcd 生成 https 证书(/etc/kubernetes/pki/)
    5、生成连接 apiserver 的 kubeconfig 文件
    6、容器启动 master 组件
    7、将涉及的配置文件存储到 configmap
    8、设置 master 节点不可调度 Pod
    9、启用 bootstrap 自动为 kubelet 颁发证书
    10、安装插件:CoreDNS、kube-proxy
    

    常见问题

    1. 证书问题

    问题: 仅火狐浏览器可访问 Dashboard

    原因: 官方提供的字签证书有问题(有效时间)

    解决方案:

    1. 删除默认的secret
    2. 用自签证书创建新的secret
    3. 修改 dashboard.yaml 文件

    2. token 失效

    $ kubeadm token create --print-join-command
    

    3. 环境清理

    $ kubeadm reset
    

    命令行操作

    kubectl --help 查看帮助信息

    kubectl create --help 查看 create 命令帮助信息

    命令 描述
    create 通过文件名或标准输入创建资源
    expose 将一个资源公开为一个新的Service
    run 在集群中运行一个特定的镜像
    set 在对象上设置特定的功能
    get 显示一个或多个资源
    explain 文档参考资料
    edit 使用默认的编辑器编辑一个资源.
    delete 通过文件名、标准输入、资源名称或标签选择器来删除资源.
    rollout 管理资源的发布
    rolling-update 对给定的复制控制器滚动更新
    scale 扩容或缩容Pod数量, Deployment、ReplicaSet、RC或Job
    autoscale 创建一个自动选择扩容或缩容并设置Pod数量
    certificate 修改证书资源
    cluster-info 显示集群信息
    top 显示资源(CPU/Memory/Storage)使用.需要Heapster运行
    cordon 标记节点不可调度
    uncordon 标记节点可调度
    drain 驱逐节点上的应用, 准备下线维护
    taint 修改节点taint标记
    describe 显示特定资源或资源组的详细信息
    logs 在一个Pod中打印一个容器日志.如果Pod只有一个容器, 容器名称是可选的
    attach 附加到一个运行的容器
    exec 执行命令到容器
    port-forward 转发一个或多个本地端口到一个pod
    proxy 运行一个proxy到Kubernetes API server
    cp 拷贝文件或目录到容器中
    auth 检查授权
    apply 通过文件名或标准输入对资源应用配置
    patch 使用补丁修改、更新资源的字段
    replace 通过文件名或标准输入替换一个资源
    convert 不同的API版本之间转换配置文件
    label 更新资源上的标签
    annotate 更新资源上的注释
    completion 用于实现kubectl工具自动补全
    api-versions 打印受支持的API版本
    config 修改kubeconfig文件(用于访问API, 比如配置认证信息)
    help 所有命令帮助
    plugin 运行一个命令行插件
    version 打印客户端和服务版本信息

    使用kubectl管理应用生命周期

    # 创建
    $ kubectl create deployment web --image=java 
    $ kubectl get deploy,pods
    
    # 发布
    $ kubectl expose deployment web --port=80 --type=NodePort --target-port=80 --name=web
    $ kubectl get service
    
    # 升级
    $ kubectl set image deployment/web nginx=nginx:1.15
    $ kubectl rollout status deployment/nginx-deployment  # 查看升级状态
    
    # 回滚
    $ kubectl rollout history deployment/web  # 查看发布记录
    $ kubectl rollout undo deployment/web   # 回滚最新版本
    $ kubectl rollout undo deployment/web --revision=2  # 回滚指定版本
    
    # 删除
    $ kubectl delete deploy/web
    $ kubectl delete svc/web
    

    常用选项

    -f, --filename=[]: 文件名、目录、或者URL创建资源
    -o, --output='': json|yaml|name|wide   所有查看的资源都可以用
    -l, --selector='': 根据标签过滤内容,支持运算符 '=', '==','!='.(示例 -l key1=value1,key2=value2)
    

    资源编排

    编写YAML注意事项

    YAML 是一种简洁的非标记语言.

    语法格式:

    • 缩进表示层级关系
    • 不支持制表符“tab”缩进, 使用空格缩进
    • 通常开头缩进 2 个空格
    • 字符后缩进 1 个空格, 如冒号、逗号等
    • “---” 表示YAML格式, 一个文件的开始
    • “#”注释
    YAML内容解析

    YAML 编排文件内容大致分为两部分:

    # 控制器相关定义
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deploy
      namespace: default
    spec:
      replicas: 2
      selector:
        matchLables:
          app: nginx
    # 被控制对象定义
        template:
          metadata:
            lables:
              app: nginx
          spec:
            containers:
            - name: nginx
              image: nginx:latest
              ports:
              - containerPort:80
    

    控制器定义:定义控制器属性
    被控制对象:Pod 模板, 定义容器属性

    具体字段意义:

    apiVersion API版本
    kind 资源类型
    metadata 资源元数据
    spec 资源规格
    replicas 副本数量
    selector 标签选择器
    template Pod模板
    metadata Pod元数据
    spec Pod规格
    containers 容器配置
    **编写 YAML **

    熟能生巧, 多写. 另外可通过如下方式快速生成, 基于实际场景修改.

    • run 命令生成部署模板

      kubectl create deployment nginx --image=nginx:1.14 -o yaml --dry-run> my-deploy.yaml

    • get 命令将已有部署的应用yaml导出

      kubectl get my-deploy/nginx -o=yaml --export > my-deploy.yaml

    • 通过 explain 查看更详细的帮助文档获得

      kubectl explain pods.spec.containers

    相关文章

      网友评论

          本文标题:容器化技术(No.2) -- Kubernetes 基础

          本文链接:https://www.haomeiwen.com/subject/fiucghtx.html