Kubernetes食用简介

Kubernetes是Google在2014年6月开源的一个容器集群管理系统,使用Go语言开发,Kubernetes也叫K8S。K8S是Google内部一个叫Borg的容器集群管理系统衍生出来的,Borg已经在Google大规模生产运行十年之久。
K8S主要用于自动化部署、扩展和管理容器应用,提供了资源调度、部署管理、服务发现、扩容缩容、监控等一整套功能;2015年7月,Kubernetes v1.0正式发布,截止到2018年8月2日最新稳定版本是v1.15.1,最新稳定版本是v1.16.0-alpha.2,Kubernetes目标是让部署容器化应用简单高效。

官方网站:https://kubernetes.io

Kubernetes主要功效

数据卷
Pod中容器之间共享数据,可以使用数据卷;
应用程序健康检
查容器内服务可能进程堵塞无法处理请求,可以设置监控检查策略保证应用健壮性;
复制应用程序实例
控制器维护着Pod副本数量,保证一个Pod或一组同类的Pod数量始终可用;
弹性伸缩
根据设定的指标(CPU利用率)自动缩放Pod副本数;
服务发现
使用环境变量或DNS服务插件保证容器中程序发现Pod入口访问地址;
负载均衡
一组Pod副本分配一个私有的集群IP地址,负载均衡转发请求到后端容器,在集群内部其他Pod可通过这个ClusterIP访问应用;
滚动更新
更新服务不中断,一次更新一个Pod,而不是同时删除整个服务;
服务编排
通过文件描述部署服务,使得应用程序部署变得更高效;
资源监控
Node节点组件集成cAdvisor资源收集工具,可通过Heapster汇总整个集群节点资源数据,然后存储到InfluxDB时序数据库,再由Grafana展示;
提供认证和授权
支持属性访问控制(ABAC)、角色访问控制(RBAC)认证授权策略;

Kubernetes基本对象概念

PodPod
是最小部署单元,一个Pod有一个或多个容器组成,Pod中容器共享存储和网络,在同一台Docker主机上运行;
Service
Service一个应用服务抽象,定义了Pod逻辑集合和访问这个Pod集合的策略,Service代理Pod集合对外表现是为一个访问入口,分配一个集群IP地址,来自这个IP的请求将负载均衡转发后端Pod中的容器,Service通过Lable Selector选择一组Pod提供服务;
Volume
数据卷,共享Pod中容器使用的数据;
Namespace
命名空间将对象逻辑上分配到不同Namespace,可以是不同的项目、用户等区分管理,并设定控制策略,从而实现多租户;命名空间也称为虚拟集群;
Lable
标签用于区分对象(比如Pod、Service),键/值对存在,每个对象可以有多个标签,通过标签关联对象;
ReplicaSet
下一代Replication Controller;确保任何给定时间指定的Pod副本数量,并提供声明式更新等功能;RC与RS唯一区别就是lable selector支持不同,RS支持新的基于集合的标签,RC仅支持基于等式的标签;
Deployment
Deployment是一个更高层次的API对象,它管理ReplicaSets和Pod,并提供声明式更新等功能,官方建议使用Deployment管理ReplicaSets,而不是直接使用ReplicaSets,这就意味着可能永远不需要直接操作ReplicaSet对象;
Stateful
SetStatefulSet适合持久性的应用程序,有唯一的网络标识符(IP),持久存储,有序的部署、扩展、删除和滚动更新;
DaemonSet
DaemonSet确保所有(或一些)节点运行同一个Pod;当节点加入Kubernetes集群中,Pod会被调度到该节点上运行,当节点从集群中移除时,DaemonSet的Pod会被删除;删除DaemonSet会清理它所有创建的Pod;
Job
一次性任务,运行完成后Pod销毁,不再重新启动新容器,还可以任务定时运行;

系统架构及组件功能

Kubernetes成分

Master组件:

kube-apiserver
Kubernetes API,集群的统一入口,各组件协调者,以HTTP API提供接口服务,所有对象资源的增删改查和监听操作都交给APIServer处理后再提交给Etcd存储;

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

kube-scheduler
根据调度算法为新创建的Pod选择一个Node节点;

Node组件:

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

kube-proxy
在Node节点上实现Pod网络代理,维护网络规则和四层负载均衡工作;

docker或rocket/rkt
运行容器;

第三方服务:

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

非必要组件:

kube-dns
负责为整个集群提供DNS服务

Ingress Controller
为服务提供外网入口

Heapster
提供资源监控

Dashboard
提供GUI

Federation
提供跨可用区的集群

Fluentd-elasticsearch
提供集群日志采集、存储与查询

系统架构及组件功能

Kubernetes食用配方

角色IP组件
master192.168.0.201etcd
kube-apiserver
kube-controller-manager
kube-scheduler
node01192.168.0.202kubelet
kube-proxy
docker
node02192.168.0.203kubelet
kube-proxy
docker
Pod 网络10.244.0.0/16
Service 网络10.96.0.0/12
  1. 获取 yum 源
  2. 安装 Docker、Kubelet、Kubeadm、Kubectl 到所有节点上
  3. Master节点初始化
  4. Flannel安装
  5. 节点加入

获取 yum 源

#进入 yum 的 repo 目录
cd /etc/yum.repos.d/
#获取 Docker 的 yum 源
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

#编写 Kubernetes 的 yum 源
vim /etc/yum.repos.d/kubernetes.repo
[Kubernetes]
name=Kubernetes Repo
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
enabled=1

#检测 yum 源的可用性
yum repolist

安装 Docker、Kubelet、Kubeadm、Kubectl 到所有节点上

#yum 安装所需部件
yum -y install docker-ce kubelet kubeadm kubectl

#启动 Docker 服务
systemctl start docker

#设置开机自启
systemctl enable docker
systemctl enable kubelet

在启动 Docker 前,由于某种不可抗力和不可描述的原因,建议国内的程序猿修改HttpsProxy的参数,具体如下:

vim /usr/lib/systemd/system/docker.service 
Environment="HTTPS_PROXY=http://www.ik8s.io:10080"
Environment="NO_PROXY=127.0.0.0/8,192.168.0.0/24"

systemctl daemon-reload
systemctl restart docker
docker info

docker.service

#检查bridge-nf
cat /proc/sys/net/bridge/bridge-nf-call-ip6tables
1
cat /proc/sys/net/bridge/bridge-nf-call-iptables
1

Master节点初始化

#配置kubelet文件,使其忽略 Swap 的报错
vim /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS="--fail-swap-on=false"

kubeadm init --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 --ignore-preflight-errors=Swap

Master节点初始化结果

#根据初始化完成后所给的提示进行设置(建议创建普通用户进行操作)
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 cs
NAME                 STATUS    MESSAGE             ERROR
scheduler            Healthy   ok                  
controller-manager   Healthy   ok                  
etcd-0               Healthy   {"health":"true"}

#查看集群节点信息
kubectl get node
NAME                  STATUS     ROLES    AGE     VERSION
centos701.if010.com   NotReady   master   9m52s   v1.15.2


#查看 docker 容器
docker ps

Docker容器

#查看 docker 镜像
docker images

Docker镜像

节点状态之所以显示 NoReady 是应为还没有安装flannel

Flannel安装

#自动拉取镜像启动
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

#查看 Pods 网络信息
kubectl get pods -n kube-system -o wide

#查看节点状态是否为 Ready 状态
kubectl get node
NAME                  STATUS   ROLES    AGE   VERSION
centos701.if010.com   Ready    master   27m   v1.15.2

节点加入集群

#加入集群
kubeadm join [MastertIP地址]:6443 --token [token值] --discovery-token-ca-cert-hash [证书哈希值] --ignore-preflight-errors=Swap

#主节点上获取节点信息
kubectl get node
NAME                  STATUS   ROLES    AGE   VERSION
centos701.if010.com   Ready    master   15h   v1.15.2
centos702.if010.com   Ready    <none>   15h   v1.15.2
centos703.if010.com   Ready    <none>   15h   v1.15.2

token值和证书哈希值在初始化集群的时候有提供

Dashboard可视化插件

#下载yaml文件到本地
wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml

#修改yaml文件,使其外网能访问
vim kubernetes-dashboard.yaml
......
---
# ------------------- Dashboard Service ------------------- #

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  type: NodePort       #增加type: NodePort
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 31620  #增加nodePort: 31620
  selector:
    k8s-app: kubernetes-dashboard

#修改配置从阿里云仓库拉取镜像
vim kubernetes-dashboard.yaml
......
 containers:
  - name: kubernetes-dashboard
    #image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1
    image: registry.cn-hangzhou.aliyuncs.com/google_containers/kubernetes-dashboard-amd64:v1.10.1
    ports:
......

#执行部署dashboard服务
kubectl create -f kubernetes-dashboard.yaml

查看Pod的状态为running说明dashboard已经部署成功
kubectl get pod --namespace=kube-system -o wide | grep dashboard

Dashboard 会在 kube-system namespace 中创建自己的 Deployment 和 Service
kubectl get deployment kubernetes-dashboard --namespace=kube-system
kubectl get service kubernetes-dashboard --namespace=kube-system

Pod的状态

访问 https://[host_ip]:31620/#!/login
dashboard web

#创建dashboard-adminuser.yaml,获取 Token
vim dashboard-adminuser.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kube-system

#执行yaml文件
kubectl create -f dashboard-adminuser.yaml

#查看admin-user账户的token
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')

查看 Token

使用获取到的 Token 值登陆 Dashboard 面板
登陆Dashboard面板

Dashboard面板

Kubernetes食用方式

#查询节点信息
kubectl describe node [节点名称]

#查看集群信息
kubectl cluster-info

#查看创建了的 Pods
kubectl get pods -o wide

#查看创建了的 Services
kubectl get services -o wide

#查看 Pod 的网络信息
kubectl describe pods [Pod名称]

#查看 Pod 的网络信息
kubectl describe service [Pod名称]


#运行Pod
kubectl run NAME --image=image [--env="key=value"] [--port=port] [--replicas=replicas] [--dry-run=bool] [--overrides=inline-json] [--command] -- [COMMAND] [args...] [options]
#栗子:
运行 Nginx
kubectl run nginx --image=nginx:1.14 --port=80 --replicas=1
运行 Busybox
kubectl run client --image=busybox --replicas=1 -it --restart=Never
--image 指定所需食用的镜像
--port 指定暴露的端口
--replicas 指定创建的个数
#删除 Pod
kubectl delete ([-f FILENAME] | [-k DIRECTORY] | TYPE [(NAME | -l label | --all)])
#栗子:
kubectl delete pods nginx-7c45b84548-7bnr6
TYPE 指定删除的是什么类型,如 services,pods
NAME 指定名称
-l 指定标签
#创建 service
kubectl expose (-f FILENAME | TYPE NAME) [--port=port] [--protocol=TCP|UDP|SCTP] [--target-port=number-or-name] [--name=name] [--external-ip=external-ip-of-service] [--type=type] [options]
#栗子:
kubectl expose deployment nginx --name=nginx-service --port=8081 --target-port=80 --protocol=TCP
deployment 指定 deployment pod 的名称
--name services的名称
--port 对外的端口
--target-port 对内的端口(pod 暴露的端口)
--protocol 指定协议
#扩展/缩减 pod的数量
kubectl scale [--resource-version=version] [--current-replicas=count] --replicas=COUNT (-f FILENAME | TYPE NAME)
#栗子:
kubectl scale --replicas=0 deployment myapp
--replicas 指定数量
#滚动升级
kubectl set image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1
#栗子:
kubectl set image deployment nginx-web nginx-web=nginx:1.10

#回滚到上一版本
kubectl rollout undo deployment [Pod名称]
#查看状态
kubectl rollout status deployment nginx-web
CONTAINER_NAME_1 pod的名称
CONTAINER_IMAGE_1 升级到那个镜像
#添加标签
kubectl label [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]
#栗子:
kubectl label pods test-pod release=canary
TYPE 指定类型,如:svc,pods
NAME 指定名称
KEY 指定键值
VAL 指定标签值

最后修改:2019 年 08 月 21 日
-