kubernetes(k8s)
简介
Kubernetes (K8s)是Google在2014年发布的一个开源项目。 据说Google的数据中心里运行着20多亿个容器,而且Google十年多前就开始使用容器技术。 最初,Google开发了一个叫Borg的系统(现在命名为Omega)来调度如此庞大数量的容器和工作负载。在积累了 这么多年的经验后,Google决定重写这个容器管理系统,并将其贡献到开源社区,让全世界都能受益。 这个项目就是Kubernetes。简单地讲,Kubernetes是Google Omega的开源版本。 从2014年第一个版本发布以来,Kubernetes迅速获得开源社区的追捧,包括Red Hat、VMware、Canonical在内 的很多有影响力的公司加入到开发和推广的阵营。目前Kubernetes已经成为发展最快、市场占有率最高的容器编 排引擎产品。
k8s的基本概念
在部署前,必须先学习Kubernetes的几个重要概念,它们是组成Kubernetes集群的基石。
Cluster (集群)
Cluster是计算、存储和网络资源的集合,Kubernetes利用这些资源运行各种基于容器的应用。
Master (控制主节点)
Master是Cluster的大脑,它的主要职责是调度,即决定将应用放在哪里运行。Master运行Linux操作系统,可以 是物理机或者虚拟机。为了实现高可用,可以运行多个Master。调度应用程序、维护应用程序的所需状态、扩展应 用程序和滚动更新都是master的主要工作。
Node (节点)
Node的职责是运行容器应用。Node由Master管理,Node负责监控并汇报容器的状态,同时根据Master的要求管 理容器的生命周期。
Node是Kubernetes集群中的工作机器,可以是物理机或虛拟机。每个工作节点都有一个kubelet,它是管理节 点并与Kubernetes Master节点进行通信的代理。节点上还应具有处理容器操作的容器运行时,例如Docker。 —个Kubernetes工作集群至少有三个节点。Master管理集群,而Node (节点)用于托管正在运行的应用程 序。 当你在Kubernetes上部署应用程序时,你可以告诉master启动应用程序容器。Master调度容器在集群的节点上 运行。节点使用Master公开的Kubernetes API与Master通信。用户也可以直接使用Kubernetes的API与集 群交互。 
Pod (资源对象)
Pod是Kubernetes的最小工作单元。每个Pod包含一个或多个容器。Pod中的容器会作为一个整体被Master调度到 一个Node上运行。
Kubernetes引入Pod主要基于下面两个目的:
- 可管理性。有些容器天生就是需要紧密联系,一起工作。Pod 提供了比容器更高层次的抽象,将它们封装到一个部署单元中。Kubernetes以Pod为最小单位进行调度、扩展、共 享资源、管理生命周期。
- 通信和资源共享。Pod中的所有容器使用同一个网络namespace,即相同的IP地址 和Port空间。它们可以直接用localhost通信。同样的,这些容器可以共享存储,当Kubernetes挂载volume到 Pod,本质上是将volume挂载到Pod中的每一个容器。
Pods有两种使用方式:
- 运行单一容器
one-container-per-Pod是Kubernetes最常见的模型,这种情况下,只是将单个容器简单封装成Pod。即便是只有 —个容器,Kubernetes管理的也是Pod而不是直接管理容器。
- 运行多个容器
问题在于:哪些容器应该放到一个Pod中?答案是:这些容器联系必须非常紧密,而且需要直接共享资源。 举个例子,如图所示,这个Pod包含两个容器: —个是File Puller(文件拉取器),一个是Web Server。

File Puller会定期从外部的Content Manager中拉取最新的文件,将其存放在共享的volume中。Web Server从 volume读取文件,响应Consumer的请求。
这两个容器是紧密协作的,它们一起为Consumer提供最新的数据;同时它们也通过volume共享数据,所以放到 一个Pod是合适的。
Controller(控制器)
Kubernetes通常不会直接创建Pod,而是通过Controller来管理Pod的。Controller中定义了Pod的部署特性,比如 有几个副本、在什么样的Node上运行等。为了满足不同的业务场景,Kubernetes提供了多种Controller,包括 Deployment、ReplicaSet、DaemonSet、StatefuleSet、Job等,我们逐一讨论。
- Deployment是最常用的Controller,比如通过创建Deployment来部署应用的。Deployment可以管理Pod的多个副本,并确保Pod按照期望的状态运行。
- ReplicaSet实现了Pod的多副本管理。使用Deployment时会自动创建ReplicaSet,也就是说Deployment是通过ReplicaSet来管理Pod的多个副本的,我们通常不需要直接使用ReplicaSet。
- DaemonSet用于每个Node最多只运行一个Pod副本的场景。正如其名称所揭示的,DaemonSet通常用于运行daemon。
- StatefuleSet能够保证Pod的每个副本在整个生命周期中名称是不变的,而其他Controller不提供这个功能。当某个Pod发生故障需要删除并重新启动时,Pod的名称会发生变化,同时StatefuleSet会保证副本按照固定的顺序启动、更新或者删除。
- Job用于运行结束就删除的应用,而其他Controller中的Pod通常是长期持续运行。
Service(服务)
Deployment可以部署多个副本,每个Pod都有自己的IP,外界如何访问这些副本呢? 通过Pod的IP吗? 要知道 Pod很可能会被频繁地销毁和重启,它们的IP会发生变化,用IP来访问不太现实。
答案是Service。 Kubernetes Service定义了外界访问一组特定Pod的方式。Service有自己的IP和端口,Service为 Pod提供了负载均衡。
Kubernetes运行容器(Pod)与访问容器(Pod)这两项任务分别由Controller和Service执行。
Namespace(命名空间)
Namespace 是对一组资源和对象的抽象集合,比如可以用来将系统内部的对象划分为不同的项目组或用户组。 如果有多个用户或项目组使用同一个Kubernetes Cluster,如何将他们创建的Controller、Pod等资源分开呢? 答 案就是Namespace。
Namespace可以将一个物理的Cluster逻辑上划分成多个虚拟Cluster,每个Cluster就是一个Namespace。不同 Namespace里的资源是完全隔离的。
Kubernetes默认创建了两个Namespace:
- default:创建资源时如果不指定,将被放到这个Namespace中。
- kube-system:Kubernetes自己创建的系统资源将放到这个Namespace中。
k8s的安装部署
k8s的搭建方式
方式一
minikube
官方给出的单机版搭建方式。
难易程度:简单
适用于:初学者
使用场景:学习
对于网络环境有要求
minikube
方式二
kubeadm
官方给出的集群版搭建方式
难易程度:偏难
适用于:工作与学习
使用场景:工作
对于网络环境有要求
kubeadm
方式三
纯手动二进制
难易程度:疯狂
适用于:工作
使用场景:工作
对于网络环境有要求
google首席布道师
中文完整流程
安装前的准备
系统版本:ubuntu18.04 LTS
机器数量:3台虚拟机
配置最低需求:1核 2G 20G硬盘
部署划分:(同一网段下三台主机)
k8s-master001: 192.168.110.116
k8s-node001: 192.168.110.117
k8s-node002: 192.168.110.118
三台机器共同基本操作
安装基本工具
#由于权限原因全程使用root用户进行操作
$ sudo -i
#安装相关软件
$ apt-get install apt-transport-https ca-certificates curl software-properties-common lrzsz -y
禁用SWAP
$ swapoff -a
$ sed -i '/ swap / s/^/#/' /etc/fstab
更新软件
#检查更新
$ apt-get update
#更新已安装软件
$ apt-get upgrade
防火墙的
#1804查看防火墙状态
$ sudo ufw status
#关闭防火墙
$ sudo ufw disable
#开启防火墙
$ sudo ufw enable
主机名的查看与设置
#查看主机名
$hostname
#设置主机名 (修改主机名需要两个文件)
$ sudo vim /etc/hostname
$ sudo vim /etc/hosts
#重启
$ reboot
Docker的安装
#docker相关软件
$ sudo apt-get install apt-transport-https ca-certificates curl software-propertiescommon lrzsz -y
#离线安装docker
$ tar xzvf docker_v18.03.1_ce.tar.gz
$ cd docker_v18.03.1_ce && ./install.sh
#配置加速器
$ curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s
http://f1361db2.m.daocloud.io
#由于全程使用root账户所以就不需要进行docker权限的设置了
master主机操作
搭建镜像仓库
#获取仓库镜像
$ docker pull registry
#启动仓库容器
$ docker run --restart=always --name=registry -d -p 5000:5000 registry
进行仓库配置
#编辑docker配置文件
sudo vim /etc/default/docker
#最末尾添加 当前仓库主机ip
DOCKER_OPTS="--insecure-registry 192.168.110.116:5000"
#创建服务依赖文件
$ sudo mkdir -p /etc/systemd/system/docker.service.d
$ sudo vim /etc/systemd/system/docker.service.d/Using_Environment_File.conf
#内容如下:
[Service]
EnvironmentFile=-/etc/default/docker
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// $DOCKER_OPTS
#重载服务配置文件
$ systemctl daemon-reload
#重启docker
$ systemctl restart docker
安装Kubeadm等程序
下载002.001.k8s.deb.v1.11.1.tar.gz
#依赖
apt-get install ethtool ebtables -y
#将002.001.k8s.deb.v1.11.1.tar.gz解压
$ tar xzvf 002.002.k8s.node.v1.11.1.tar.gz
#进入文件夹
$ cd k8s.deb.v1.11.1
#启动安装脚本
$ ./install.sh
#脚本内容
dpkg -i apt-transport-https_1.6.3_all.deb
#k8s网络接口插件
dpkg -i kubernetes-cni_0.6.0-00_amd64.deb
dpkg -i cri-tools_1.11.0-00_amd64.deb
dpkg -i socat_1.7.3.2-2ubuntu2_amd64.deb
#kubelet:负责 Pod 的创建、启动、监控、重启、销毁等工作,同时与 Master 节点协作,实现集群管理的基本功能。
dpkg -i kubelet_1.11.1-00_amd64.deb
#命令行工具
dpkg -i kubectl_1.11.1-00_amd64.deb
#kubeadm官方给出的安装方法
dpkg -i kubeadm_1.11.1-00_amd64.deb
导入k8s安装所需镜像
#解压压缩包
$ tar xzvf 002.002.k8s.master.v1.11.1.tar.gz
#进入文件进行安装
$ cd k8s.master.v1.11.1
#运行脚本进行镜像的导入
$ ./loadall.sh
安装k8s
#解压压缩包
$tar xzvf 003.kubeadm_init.tar.gz
#进入文件
cd kubeadm_init
#进行初始化安装
$ ./kubeadm_init.sh #注意修改脚本中初始化的网络地址
执行后内容
Your Kubernetes master 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/
You can now join any number of machines by running the following on each node
as root:
#其他的都不是太重要主要是这一句是用来让其他node节点加入集群的操作所以要保存
kubeadm join 192.168.110.158:6443 --token ttw6dz.d2v8nqtyx5kipxlu --discoverytoken-ca-cert-hash
sha256:df233ca36396ba0ecc2b727ca8b4dd6074091c27f7644ae054d671d5b0d27b79
clusterrole.rbac.authorization.k8s.io/calico-node created
clusterrolebinding.rbac.authorization.k8s.io/calico-node created
configmap/calico-config created
service/calico-typha created
deployment.apps/calico-typha created
daemonset.extensions/calico-node created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
serviceaccount/calico-node created
如果失败
#如果创建失败或者是集群加入失败可以使用如下命令重新开始
kubeadm reset重新设置
Node节点操作
设置加速器文件
#执行加速器命令
$ curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io
#修改加速器文件
sudo vim /etc/docker/daemon.json
#内容如下 的ip为默认使用的仓库
{"registry-mirrors": ["http://f1361db2.m.daocloud.io"],"insecure-registries": ["192.168.110.116:5000"]}
安装Kubeadm等程序
#依赖
apt-get install ethtool ebtables -y
#将002.001.k8s.deb.v1.11.1.tar.gz解压
$ tar xzvf 002.002.k8s.node.v1.11.1.tar.gz
#进入文件夹
$ cd k8s.deb.v1.11.1
#启动安装脚本
$ ./install.sh
安装node节点相关程序
#解压
tar xzvf 004.kubernetes-dashboard.tar.gz
#进入
cd kubernetes-dashboard
#执行脚本
./install.sh
使用命令加入集群
#这个命令是在创建master的时候或得到的
$ kubeadm join 192.168.110.116:6443 --token clgahe.stw4d93ihds0k5d4 --discoverytoken-ca-cert-hash sha256:2ccc882ca893f79749fe7ba8e81a9ed87772cfff4dda6f88db68b6858e00081b
#如果不成功请重新来过
在Master上安装Dashboard
web ui 图形化界面
#解压
$ tar xzvf 004.kubernetes-dashboard.tar.gz
#进入
$ cd kubernetes-dashboard
#执行
$ ./install.sh
k8s的基本命令
环境变量设置
#默认情况下,我们没有办法直接使用tab方式补全kubernetes的命令
#获取相关环境配置
kubectl completion bash
#加载这些配置
source <(kubectl completion bash)
#注意: "<(" 两个符号之间没有空格放到当前用户的环境文件中
echo "source <(kubectl completion bash)" >> ~/.bashrc
#测试效果
kubectl dedelete describe
查看全部信息
kubectl get service,pods,deployment,nodes,namespaces -o wide
docker run
使用docker
$ docker run -d --name nginx-app -p 80:80 nginx
a9ec34d9878748d2f33dc20cb25c714ff21da8d40558b45bfaec9955859075d0
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a9ec34d98787 nginx "nginx -g 'daemon of 2 seconds ago Up 2 seconds 0.0.0.0:80->80/tcp, 443/tcp nginx-app
使用kubectl:
# start the pod running nginx
$ kubectl run --image=nginx nginx-app --port=80 --env="DOMAIN=cluster"
docker ps
使用docker:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a9ec34d98787 nginx "nginx -g 'daemon of About an hour ago Up About an hour 0.0.0.0:80->80/tcp, 443/tcp nginx-app
与kubectl:
$ kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-app-5jyvm 1/1 Running 0 1h
docker exec
如何在容器中执行命令?参考kubectl_exec 使用docker:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a9ec34d98787 nginx "nginx -g 'daemon of 8 minutes ago Up 8 minutes 0.0.0.0:80->80/tcp, 443/tcp nginx-app
$ docker exec a9ec34d98787 cat /etc/hostname
a9ec34d98787
使用kubectl:
$ kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-app-5jyvm 1/1 Running 0 10m
$ kubectl exec nginx-app-5jyvm -- cat /etc/hostname
nginx-app-5jyvm
交互式命令
使用docker:
$ docker exec -ti a9ec34d98787 /bin/sh
# exit
使用kubectl:
$ kubectl exec -ti nginx-app-5jyvm -- /bin/sh
# exit
docker logs
使用docker:
$ docker logs -f a9e
192.168.9.1 - - [14/Jul/2015:01:04:02 +0000] "GET / HTTP/1.1" 200 612 "-"
"curl/7.35.0" "-"
192.168.9.1 - - [14/Jul/2015:01:04:03 +0000] "GET / HTTP/1.1" 200 612 "-"
"curl/7.35.0" "-"
使用kubectl:
$ kubectl logs -f nginx-app-zibvs
10.240.63.110 - - [14/Jul/2015:01:09:01 +0000] "GET / HTTP/1.1" 200 612 "-"
"curl/7.26.0" "-"
10.240.63.110 - - [14/Jul/2015:01:09:02 +0000] "GET / HTTP/1.1" 200 612 "-"
"curl/7.26.0" "-"
docker stop 和 docker rm
使用docker:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
a9ec34d98787 nginx "nginx -g 'daemon of 22 hours ago Up
22 hours 0.0.0.0:80->80/tcp, 443/tcp nginx-app
$ docker stop a9ec34d98787
a9ec34d98787
$ docker rm a9ec34d98787
a9ec34d98787
使用kubectl:
$ kubectl get deployment nginx-app
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-app 1 1 1 1 2m
$ kubectl get po -l run=nginx-app
NAME READY STATUS RESTARTS AGE
nginx-app-2883164633-aklf7 1/1 Running 0 2m
$ kubectl delete deployment nginx-app
deployment "nginx-app" deleted
$ kubectl get po -l run=nginx-app
# Return nothing
注意,不要直接删除pod,使用kubectl请删除拥有该pod的Deployment。如果直接删除pod,则Deployment将会重新创建该pod。
docker version
使用docker:
$ docker version
Client version: 1.7.0
Client API version: 1.19
Go version (client): go1.4.2
Git commit (client): 0baf609
OS/Arch (client): linux/amd64
Server version: 1.7.0
Server API version: 1.19
Go version (server): go1.4.2
Git commit (server): 0baf609
OS/Arch (server): linux/amd64
使用kubectl:
$ kubectl version
Client Version: version.Info{Major:"0", Minor:"20.1", GitVersion:"v0.20.1",GitCommit:"", GitTreeState:"not a git tree"}
Server Version: version.Info{Major:"0", Minor:"21+", GitVersion:"v0.21.1-411-g32699e873ae1ca-dirty", GitCommit:"32699e873ae1caa01812e41de7eab28df4358ee4",GitTreeState:"dirty"}
docker info
使用docker:
$ docker info
使用kubectl:
$ kubectl cluster-info
docker inspect
使用docker:
$ docker inspect nginx
使用kubectl:
$ kubectl describe deployment.extensions/nginx-app