k8s学习笔记

1. 环境准备

# 关闭swap
swapoff -a
# 安装kubectl kubelet kubeadm
sudo apt-get install -y kubectl kubelet kubeadm
sudo systemctl enable kubelet && sudo systemctl start kubelet
# 开启bash自动补全
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc
# docker镜像加速
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://uyah70su.mirror.aliyuncs.com"]
}
EOF

2. kubenetes简介

2.1 kubenetes架构

架构

  • kubeadm 负责初始化cluster

  • kubectl 作为k8s的命令行工具,可以部署和管理应用,查看各种资源,创建/安装/删除各种组建。

  • etcd 是一个分布式k-v数据库。

  • master 负责管理整个集群的node

  • node 是pod实际运行的机器

  • pod 一组紧密联系的容器放在一个pod中,例如一个微服务和一个日志收集容器。pod是k8s调度的最小单位。同一个pod内的所有容器共享ip和端口号,也就是说它们在同一个网络内。

  • scheduler 运行在master,负责将pod放到哪个node上运行

  • api server 运行在master,负责提供k8s的restful接口

  • controller 在k8s中,针对不同应用场景,提供了很多个controller,典型的有:Deployment,ReplicaSet,DaemonSet,StatefuleSet,Job

  • kubelet 不管是maste还是每个node都只有一个kubelet,当scheduler决定在哪个node上面运行pod后,将pod的配置发送给kubelet,kubelet负责启动pod和容器,同时也向master报告运行状态。它是唯一没有通过容器化运行的组建,所以,一开始我们就得和kubectl、kubeadm一起安装kubelet。

  • service 每个node都只有一个service,service代表了多个pod,外界通过service来访问pod

  • kube-proxy 不管是maste还是每个node都最多只有一个kube-prroxy,也可以没有。外界在请求pod时,先请求service,kube-proxy把请求再转发给pod

  • kube-dns 整个集群的dns,在执行kubectl init时自动run容器。

  • flannel 一种网络解决方案。它可以把所有的pod组成“平级”的、每个容器都有唯一ip的网络。

  • pause

  • label 默认情况下,k8s会自动调度pod到所有的node上运行,如果想调用pod到指定的node,这时候就可以通过label来区分pod,例如,将I/O频繁的pod调度到有ssd的node上,将可以利用显卡进行浮点计算的pod调度到安装有高性能显卡的nde上运行。

  • selector

  • deployment

  • ReplicaSet 在旧版本的Kubernetes中,只有ReplicationController对象。它的主要作用是确保Pod以你指定的副本数运行,即如果有容器异常退出,会自动创建新的 Pod 来替代;而异常多出来的容器也会自动回收。在新版本的 Kubernetes 中建议使用 ReplicaSet。ReplicaSet 跟 ReplicationController 没有本质的不同,只是名字不一样,并且 ReplicaSet 支持集合式的 selector(ReplicationController 仅支持等式)。

    deployment、ReplicaSet、pod的关系

为什么maste也有kubelet和kube-proxy?

因为master也是一个node,也可以运行pod。

2.2 kubenetes运行流程

3. 安装cluster

导出镜像列表

kubeadm config images list --kubernetes-version=v1.18.5
得到如下这些镜像:
k8s.gcr.io/kube-apiserver:v1.18.5
k8s.gcr.io/kube-controller-manager:v1.18.5
k8s.gcr.io/kube-scheduler:v1.18.5
k8s.gcr.io/kube-proxy:v1.18.5
k8s.gcr.io/pause:3.2
k8s.gcr.io/etcd:3.4.3-0
k8s.gcr.io/coredns:1.6.7
配置docker镜像加速后下载上述镜像。

在node1和node2上执行拉取镜像

vi pull-k8s.sh

#!/bin/bash
KUBE_VERSION=v1.18.5
KUBE_PAUSE_VERSION=3.2
ETCD_VERSION=3.4.3-0
DNS_VERSION=1.6.7
username=kubesphere

images=(
        kube-proxy-amd64:${KUBE_VERSION}
        kube-scheduler-amd64:${KUBE_VERSION}
        kube-controller-manager-amd64:${KUBE_VERSION}
        kube-apiserver-amd64:${KUBE_VERSION}
        pause:${KUBE_PAUSE_VERSION}
        etcd-amd64:${ETCD_VERSION}
        coredns:${DNS_VERSION}
    )

for image in ${images[@]}
do
    docker pull ${username}/${image}
    docker tag ${username}/${image} k8s.gcr.io/${image}
    docker rmi ${username}/${image}
done

在master上执行初始化集群和安装集群

# 初始化集群
sudo kubeadm init --apiserver-advertise-address 192.168.0.220 --pod-network-cidr=10.244.0.0/16

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 安装flannel网络
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

# 创建deployment
## 生成yaml文件
kubectl create deployment tomcat-web-server --image=tomcat:9.0 -o yaml --dry-run=client > tomcat-web-deployment.yaml
## 部署容器,kubectl生成deployment->ReplicaSet->Pod
kubectl apply -f tomcat-web-deployment.yaml 
## 查看部署情况
kubectl get nodes --show-labels
kubectl get deployment
kubectl get replicaset
kubectl get pods
kubectl get pod -o wide
kubectl describe pod tomcat-web-server-84ffc789c4-ftxwh
kubectl describe deployment tomcat-web-server
kubectl describe replicaset tomcat-web-server-84ffc789c4

## 删除应用
kubectl delete -f tomcat-web-deployment.yaml 
## 伸缩
修改tomcat-web-deployment.yaml 文件的副本数量,执行kubectl apply -f tomcat-web-deployment.yaml 

# 创建service
## 生成yaml文件
kubectl expose deployment tomcat-web-server --port=8989 --target-port=8080 --dry-run=client -o=yaml > tomcat-web-server-service.yaml
kubectl apply -f tomcat-web-server-service.yaml
kubectl get service
kubectl describe service tomcat-web-server-service
kubectl delete -f ./tomcat-web-server-service.yaml

在node上面运行

# 把node加入集群
sudo kubeadm join 192.168.0.220:6443 --token yoz6r2.kq6p0bbk7nka3mu1     --discovery-token-ca-cert-hash sha256:1c21804199a80d4e18cea7aa114fdf030162f224c7e86ed061ac88f7397e31f4 

这里的token来自于一开始运行kubeadm init得到的token,如果没有记录下来,可以在master上面运行下面的命令,就能得到token
kubeadm token list

至此,k8s部署完毕了。下来我们看k8s相关的知识。

4. 管理资源

kubectl create
kubectl replace
kubectl edit
kubectl patch

管理node

# 查看所有node
kubectl get nodes

管理pod

基本用法

# 查看所有pod
kubectl get pod --all-namespace
# 查看某个pod
kubectl describe pod <pod-name> --namesace=xxx -o wide
查看已有pod的配置
kubectl get pod gott-trade-center -o yaml

使用 kubectl explain 来发现可能的 API 对象字段
kubectl explain pods

上述命令打印出对象的解释并列出对象可以包含的属性,接下来就可以深入了解各个属性的更多信息 。例如,可以这样查看 spec 属性 :
kubectl explain pod.spec

使用 kubectl create 来创建 pod
kubecl create -f kubia-manual.yaml

在pod列表中查看新创建的pod
kubectl get pods

暴露pod的端口给外部
kubectl port-forward kubia-manual 8888:8080

多个容器放到一个pod还是多个pod?

  • 它们需要一起运行还是可以在不同的主机上运行?
  • 它们代表的是一个整体还是相互独立的组件?
  • 它们必须一起进行扩缩容还是可以分别进行?

5. 应用

5.1 deployment

deployment是最常用的controller,工作在ReplicaSet之上,用于管理无状态应用。支持滚动更新和回滚功能。

管理deployment

# 创建deployment
两种方式,一种是运行命令,如下所示
kubectl run <deployment-name> --image=nginx/nginx:1.7.2 --replicas=3
另外一种是通过配置文件kubectl appy -f xxx.yaml创建。
# 查看deployment的状态
kubectl get deployment <deployment-name>
# 查看deployment的详细信息
kubectl describe deployment <deployment-name>
# 根据应用获取yaml文件
kubectl edit deployment <deployment-name> --namespace=<namespace-name>

调度pod到指定node

默认情况下,k8s会自动调度pod到所有的node上运行,如果想调用pod到指定的node,这时候就可以通过label来区分pod,例如,将I/O频繁的pod调度到有ssd的node上,将可以利用显卡进行浮点计算的pod调度到安装有高性能显卡的nde上运行。

可以通过label命令给所有的资源添加标签的功能。label的用法:

# 给demo-node1的节点添加disktype=ssd的标签
kubectl label node node1 disktype=ssd
# 查看node的时候,列出来标签
kubectl get node --show-labels
# 删除node1的label(删除后,k8s并不会因为node1没有了disktype标签而重新自动调度pod到其他机器),如果需要重新调度pod,则需要删除pod的nodeSelector的label属性,然后运行kubectl apply -f xxxx.yaml
kubectl label node node1 disktype-

在创建label时,可以通过指定nodeSelector的disktype属性,如果指定disktype=ssd,那么controller将会在标记有labe的键值对disktype=ssd的node上面创建和运行pod。

通过label调度

5.2 DaemonSet

DeploymentController允许在一个node上面部署多个pod副本(这里是pod副本,也就是说多个相同的pod),而DaemonSet不同,一个node上面只运行部署一个pod副本。使用方式:

# 查看正在以daemonset方式运行的k8s系统组件
kubectl get daemonset -n=kube-system
我们发现,kube-proxy和kube-flannel都是以daemon方式运行的。

DaemonSet的典型使用场景:

  • 在每个cluster的每个node上运行存储Daemon,例如ceph;

  • 在每个node上运行日志收集Daemon,例如elk之一的logstash;

  • 在每个node上运行监控Daemon,例如prometheus。

5.3 ReplicaSet

代用户创建指定数量的pod副本数量,确保pod副本数量符合预期状态,并且支持滚动式自动扩容和缩容功能。

5.4 Job

只要完成就立即退出,不需要重启或重建。

5.5 Cronjob

周期性任务控制,不需要持续后台运行,

5.6 StatefulSet

管理有状态应用

6. service

我们知道,当pod出现故障或者修改副本数等情况导致重新部署时,如果没有指定特定node,那么,pod可以被controller调度到不同node上,这意味着ip随时都会变化。当pod的ip发生变化时,如何访问pod呢?k8s提供了service。service从逻辑上代表了一组pod,service的selector和pod的label相一致时,service就代表这这一组pod。

6.1 cluster中访问service

cluster中访问service有2种方式,分别是ClusterIp、kube-dns

  • ClusterIp:ClusterIp的实现方式是iptables,大致思路是:每个node上有一个StatefulSet创建的service用来维护该node上的iptables规则,访问service的虚拟ip时,该node的iptables会通过规则转发到对应pod上。这也是默认的方式。

  • kube-dns:当新建service时,kube-dns会自动添加Service的dns记录。cluster中的pod可以通过.访问service。

6.2 外网访问service

k8s提供了3种访问外网的方式:

  • ClusterIp

  • NodePort 外网可以通过:的方式访问service。这里的NodePort不是service的port,也不是container的port,而是k8s自动分配给node的port,当然也可以在配置文件中指定。

  • LoadBalancer

7. 数据存储

  • 持久化存储

    • PV
    • PVC
  • 非持久化存储

    • emptyDir 这种方式的作用是将node上的空目录挂载到容器。生命周期和pod相同。

    • hostpath 将node上的非空目录挂载到容器。

8. Secret和Configmap

容器启动时需要一些配置,如果这些配置是重要且敏感的,例如私钥/token,那么,放到镜像里显然不合适。k8s提供了secret,并且以密文的形式保存。secret有2种使用方式,volumn方式和环境变量方式。

secret

  • volumn方式:Secret会以volumn的形式mount到pod中去

  • 环境变量方式

configmap

与secret不同,configmap是以明文的方式存放,适合存储非敏感数据,例如配置文件

9. 监控

9.1 日志

# 返回仅包含一个容器的pod的日志
$ kubectl logs <pod-name>

# 一个pod有多个container时,返回pod中已经停止的容器web-1的日志快照
$ kubectl logs <pod-name> -c <containe-name>

# 一个pod有多个container时,持续输出pod中的容器的日志
$ kubectl logs <pod-name> -f -c <containe-name>

# 仅输出pod中最近的20条日志
$ kubectl logs --tail=20 <pod-name>

# 输出pod中最近一小时内产生的所有日志
$ kubectl logs --since=1h <pod-name>

9.2 安装dashboard

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.3/aio/deploy/recommended.yaml
# 生成令牌
kubectl -n kube-system describe $(kubectl -n kube-system get secret -n kube-system -o name | grep namespace) | grep token

参考文献

[1]CloudMan.每天5分钟玩转Kubernetes[M].清华大学出版社:北京,2018-03-01:1-22.

posted @ 2020-09-06 11:58  一叶(foolishnoob)  阅读(428)  评论(0编辑  收藏  举报