Kubernetes 部署

更新链接: https://github.com/mushuanli/wsue/wiki/Kubernetes-%E9%83%A8%E7%BD%B2

1. 介绍

1.1 docker介绍

docker 是kubertnetes的运行基础。在了解kubernetes前应当先了解docker.

1.1.1 介绍

软件开发会趋于复杂,带来的最大的麻烦在于环境配置。特别是不同的应用有不同的依赖,当软件升级时,依赖冲突经常变成难以解决的问题。

传统解决环境配置的方法是针对不同应用使用不同虚拟机部署,但是虚拟机耗费资源,而且性能损失不小,同时启动慢。

另外一种方式就是使用名字空间和资源分组对应用进行隔离,使应用运行在自己的虚拟环境中(但是不会进行整个系统的虚拟)。由于不需要进行操作系统级别的虚拟化,仅进行应用运行环境的隔离,优点是资源占用小,启动快,性能损失少。这个典型的解决方案是docker。

[图片上传失败...(image-c77651-1564578806788)]

同时由于docker封装了应用和运行环境, 这个特点很适合把传统应用微服务化。微服务化可以使软件实现弹性扩展、快速迭代,促进DevOps(DevOps 强调的是高效组织团队之间如何通过自动化的工具协作和沟通来完成软件的生命周期管理,从而更快、更频繁地交付更稳定的软件。有工具支持,运维关注代码,开发关注部署,效率和质量都能得到提升。)

[图片上传失败...(image-88aa46-1564578806788)]

1.1.2 docker 依赖技术

Docker中的容器化是通过依赖两大技术:

  • 资源隔离(cgroups),内核名称空间(隔离应用程序的操作系统视图,进程树等)
  • 支持联合的文件系统(例如aufs - 将多个目录安装到一个看似于包含它们的组合内容)。

[图片上传失败...(image-217cc0-1564578806789)]

1.1.3 docker 概念

docker 有3个核心概念:

  • 镜像(Image): 应用程序映像。
    镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。

  • 容器(Container):正在运行的Image。但是运行的Image不会修改Image本身内容,所有对Image的改动在容器停止运行后丢失,为了避免数据丢失可以在运行时mount 本地目录。

  • 仓库(Docker registry): Docker 仓库是集中存放镜像文件的场所。镜像构建完成后,可以很容易的在当前宿主上运行。
    但是, 如果需要在其他服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry(仓库注册服务器)就是这样的服务。

另外:

  • Dockerfile: 声明了Image 怎样被创建的规则。

下面是他们的关系列表:

[图片上传失败...(image-5604bb-1564578806789)]

容器和映像的文件系统关系如下:
容器在映像上面增加了一个可写层,但是每一次容器退出,这个可写层的内容就丢失,所以容器每一次运行文件系统都是相同的:

[图片上传失败...(image-60546c-1564578806789)]

1.1.4 第一个例子: 在CentOS上运行 Ubuntu

这个例子体现了docker作为轻量级虚拟机的特点(共用内核,但是系统不一样):

安装Docker:

yum install -y docker
systemctl enable docker && systemctl start docker

用 docker pull ubuntu 把ubuntu下载到本地:

[root@localhost ~]# docker images
REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
[root@localhost ~]# docker pull ubuntu
Using default tag: latest
Trying to pull repository docker.io/library/ubuntu ...
latest: Pulling from docker.io/library/ubuntu
6abc03819f3e: Pull complete
05731e63f211: Pull complete
0bd67c50d6be: Pull complete
Digest: sha256:f08638ec7ddc90065187e7eabdfac3c96e5ff0f6b2f1762cf31a4f49b53000a5
Status: Downloaded newer image for docker.io/ubuntu:latest
[root@localhost ~]# docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
docker.io/ubuntu          latest              7698f282e524        3 weeks ago         69.9 MB

docker images 看到ubuntu到镜像仅 69MB 大小,这比起虚拟机来小太多了。而后面安装应用程序时仅添加应用程序的依赖,使得环境很简洁。

运行ubuntu:

[root@localhost ~]# ls /home/
admin  enable  manager 
[root@localhost ~]# docker run -it --rm -v /home/:/builddir ubuntu /bin/bash
root@90f65fac1f07:/# ls /builddir/
admin  enable  manager 
root@1f610ad274b3:/# apt list
Listing... Done
adduser/now 3.116ubuntu1 all [installed,local]
apt/now 1.6.10 amd64 [installed,local]
base-files/now 10.1ubuntu2.4 amd64 [installed,local]
base-passwd/now 3.5.44 amd64 [installed,local]
bash/now 4.4.18-2ubuntu1 amd64 [installed,local]
......

另外启动一个终端,使用docker ps 可以看到容器已经运行, ifconfig 看到docker0网桥,和 veth 开始的表示给容器使用的网卡, docker inspect 查看容器信息:

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
b6f0b23e4077        ubuntu              "/bin/bash"         14 seconds ago      Up 13 seconds                           elated_minsky
[root@localhost ~]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.248.1  netmask 255.255.248.0  broadcast 0.0.0.0
        ether 02:42:6d:d7:a8:44  txqueuelen 0  (Ethernet)
        RX packets 54  bytes 3544 (3.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.206.138.103  netmask 255.255.252.0  broadcast 10.206.139.255
        ether 00:0c:29:10:f5:82  txqueuelen 1000  (Ethernet)
        RX packets 1313112  bytes 831831412 (793.2 MiB)
        RX errors 0  dropped 40  overruns 0  frame 0
        TX packets 436949  bytes 643904800 (614.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth9620c4e: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        ether 86:46:62:9e:64:be  txqueuelen 0  (Ethernet)
        RX packets 13  bytes 1006 (1006.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2  bytes 140 (140.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
[root@localhost ~]# docker inspect b6f0b23e4077
[
    {
        "Id": "c6041b62d5426c4467687918ea5e741bd4cfb215dced172d750ff4b9b4520404",
        "Created": "2019-06-09T03:35:06.651278353Z",
        "Path": "/bin/bash",
   ......

docker run -it --rm -v /home/:/builddir ubuntu /bin/bash 意义:

  • -i : interactive 交互模式, 可以输入命令
  • -t : tty 分配一个控制台
  • --rm: 当容器退出时清除容器文件系统
  • -v /home/:/builddir : 把本地的/home目录映射到容器内的 /builddir 目录
  • ubuntu: 镜像名称
  • /bin/bash: 容器启动的命令。

在容器中可以象在真实系统中一样读写,但是仅在映射的目录下的改动才会保存。
按control-d 或是输入 exit 退出 /bin/bash, 同时发现容器也退出了,docker ps 看不到容器信息。
上面就体验到容器就是应用程序的执行环境,当应用程序退出后容器也就退出了。

1.1.5 第二个例子: 启动nginx 服务

上面的例子体验了容器访问本地目录功能
这个例子体验容器当成服务器运行功能, 体现了docker 作为服务器应用的分发工具特色(一个镜像就是应用的完整运行环境,即拉即用(pull and run))。

[root@localhost ~]# docker pull nginx
Using default tag: latest
Trying to pull repository docker.io/library/nginx ...
latest: Pulling from docker.io/library/nginx
743f2d6c1f65: Pull complete
d6c2f01b1dae: Pull complete
d4da6ff1b555: Pull complete
Digest: sha256:12db363acf5b2d2f9f5fed240e228a04692bdac68402430fbd2f720c3a967d01
Status: Downloaded newer image for docker.io/nginx:latest
[root@localhost ~]# docker images
REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
docker.io/nginx           latest              62c261073ecf        4 days ago          109 MB
docker.io/ubuntu          latest              7698f282e524        3 weeks ago         69.9 MB

可见nginx 才109MB

下面是运行,这次是后台运行,所以原来的 -it 不用(交互和控制台),取代成 -d (守护模式)
同时加了 -p 8081:80 表示把本地的8081 tcp端口映射到 容器内的 80 端口
最后使用 curl 访问了一下,发现访问成功。

[root@localhost ~]# docker run --name runoob-nginx-test -p 8081:80 -d nginx
384f1d5ad031306237e338f6e0e7e711f539dd12f48c9d136dfe760dc62ba721
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
384f1d5ad031        nginx               "nginx -g 'daemon ..."   7 seconds ago       Up 5 seconds        0.0.0.0:8081->80/tcp   runoob-nginx-test
[root@localhost ~]# cu
curl  cut
[root@localhost ~]# curl localhost:8081
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

运行完后使用 docker kill 停止容器。

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
384f1d5ad031        nginx               "nginx -g 'daemon ..."   3 minutes ago       Up 3 minutes        0.0.0.0:8081->80/tcp   runoob-nginx-test
[root@localhost ~]# docker kill 384f1d5ad031
384f1d5ad031
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

1.1.6 docker 命令介绍

[图片上传失败...(image-317d3c-1564578806789)]

1.1.7 构建自己的镜像

构建自己的镜像有多个方法,例如直接从 tar 包生成,
但是大部分镜像都是继承某个系统,例如在ubuntu或是centos (因为大部分应用都是在某个系统上开发)
这时就使用dockerfile, 下面是它的一个例子:
Dockerfile文件格式如下:

##  Dockerfile文件格式

# This dockerfile uses the ubuntu image
# VERSION 2 - EDITION 1
# Author: docker_user
# Command format: Instruction [arguments / command] ..
 
# 1、第一行必须指定 基础镜像信息
FROM ubuntu
 
# 2、维护者信息
MAINTAINER docker_user docker_user@email.com
 
# 3、镜像操作指令
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
 
# 4、容器启动执行指令
CMD /usr/sbin/nginx

Dockerfile 分为四部分:基础镜像信息、维护者信息、镜像操作指令、容器启动执行指令。

  • 一开始必须要指明所基于的镜像名称,
  • 接下来一般会说明维护者信息;
  • 后面则是镜像操作指令,例如 RUN 指令。每执行一条RUN 指令,镜像添加新的一层,并提交;
  • 最后是 CMD 指令,来指明运行容器时的操作命令。

构建

docker build -f /path/to/a/Dockerfile .

构建好后 docker images 可以看到新建的镜像.

1.2. kubernetes介绍

Kubernetes(k8s)是Google开源的容器集群管理系统(谷歌内部:Borg), 在Docker技术的基础上,为容器化的应用提供部署运行、资源调度、服务发现和动态伸缩等一系列完整功能,提高了大规模容器集群管理的便捷性。下面是他的主要功能:

[图片上传失败...(image-f4cded-1564578806789)]

kubernetes的两个设计理念依赖:

  1. docker。
    它让开发者将自己的应用以及依赖打包到一个可移植的容器中,让应用程序的运行可以实现环境无关。docker是微服务良好的载体。

  2. 微服务。
    随着软件变得越来越复杂,一个完整的后端服务不再是单体服务,而是由多个职责和功能不同的服务组成,服务之间复杂的拓扑关系以及单机已经无法满足的性能需求使得软件的部署和运维工作变得非常复杂,这也就使得部署和运维大型集群变成了非常迫切的需求。微服务应运而生。

Kubernetes优势:

  • - 容器编排
  • - 轻量级
  • - 开源
  • - 弹性伸缩
  • - 负载均衡

kubernetes架构,如下图,由一个master和多个worker(也叫Node/Slave)组成, Master负责管理集群,提供集群的资源数据访问入口, Worker(Node/Slave)用来承载被分配Pod的运行,是Pod运行的宿主机:

[图片上传失败...(image-5002c3-1564578806789)]

内部工作流程交互如下:

[图片上传失败...(image-41c445-1564578806789)]

1.3. kubernetes关键概念

1.3.1. Master

k8s集群的管理节点,负责管理集群,提供集群的资源数据访问入口。
[图片上传失败...(image-a5980b-1564578806789)]

拥有Etcd存储服务(可选),运行Api Server进程,Controller Manager服务进程及Scheduler服务进程,关联工作节点Node。

Kubernetes API server提供HTTP Rest接口的关键服务进程,是Kubernetes里所有资源的增、删、改、查等操作的唯一入口。也是集群控制的入口进程;

Kubernetes Controller Manager是Kubernetes所有资源对象的自动化控制中心;

Kubernetes Schedule是负责资源调度(Pod调度)的进程。

1.3.2. Node(Worker)

[图片上传失败...(image-eba528-1564578806789)]

Node是Kubernetes集群操作的单元,用来承载被分配Pod的运行,是Pod运行的宿主机。关联Master管理节点,拥有名称和IP、系统资源信息。

运行docker eninge服务,守护进程kunelet及负载均衡器kube-proxy.
每个Node节点都运行着以下一组关键进程
kubelet:负责对Pod对于的容器的创建、启停等任务
kube-proxy:实现Kubernetes Service的通信与负载均衡机制的重要组件
Docker Engine(Docker):Docker引擎,负责本机容器的创建和管理工作。

1.3.3. POD

在Kubernetes中最小的部署单位。

[图片上传失败...(image-62b464-1564578806789)]

Pod由一至多个容器所组成,而在一般应用层面上由于下述几点原因,使其较接近于一般使用的VM:

  • 共享同样的IP位址及Port space
    同个Pod内的容器可以透过localhost来互相沟通

Pod可以直接透过该IP和其他Pod进行联系,但一般而言我们会透过service来取代直接Pod存取

  • 共享储存空间(volumes)
  • 耦合性较高之应用,例如:

[图片上传失败...(image-26dc45-1564578806789)]

为什么不直接在一个容器中运行多个应用程序呢?

  • 透明。让Pod中的容器对基础设施可见,以便基础设施能够为这些容器提供服务,例如进程管理和资源监控。这可以为用户带来极大的便利。
  • 解耦软件依赖。每个容器都可以进行版本管理,独立的编译和发布。未来kubernetes甚至可能支持单个容器的在线升级。
  • 使用方便。用户不必运行自己的进程管理器,还要担心错误信号传播等。
  • 效率。因为由基础架构提供更多的职责,所以容器可以变得更加轻量级。

1.3.4. Replication Controller/RS/Deployment

副本控制器(Replication Controller,RC)

用来管理Pod的副本,保证集群中存在指定数量的Pod副本。

集群中副本的数量大于指定数量,则会停止指定数量之外的多余容器数量,反之,则会启动少于指定数量个数的容器,保证数量不变。

Replication Controller是实现弹性伸缩、动态扩容和滚动升级的核心。

副本集(Replica Set,RS)

RS是新一代RC,提供同样的高可用能力,区别主要在于RS后来居上,能支持更多种类的匹配模式。副本集对象一般不单独使用,而是作为Deployment的理想状态参数使用。

部署(Deployment)

部署表示用户对Kubernetes集群的一次更新操作。部署是一个比RS应用模式更广的API对象,可以是创建一个新的服务,更新一个新的服务,也可以是滚动升级一个服务。滚动升级一个服务,实际是创建一个新的RS,然后逐渐将新RS中副本数增加到理想状态,将旧RS中的副本数减小到0的复合操作;这样一个复合操作用一个RS是不太好描述的,所以用一个更通用的Deployment来描述。以Kubernetes的发展方向,未来对所有长期伺服型的的业务的管理,都会通过Deployment来管理。

有状态服务集(StatefulSet)

  • RC和RS主要是控制提供无状态服务的,其所控制的Pod的名字是随机设置的,一个Pod出故障了就被丢弃掉,在另一个地方重启一个新的Pod,名字变了。名字和启动在哪儿都不重要,重要的只是Pod总数;

  • 而StatefulSet是用来控制有状态服务,StatefulSet中的每个Pod的名字都是事先确定的,不能更改。

  • 对于RC和RS中的Pod,一般不挂载存储或者挂载共享存储,保存的是所有Pod共享的状态,Pod像牲畜一样没有分别(这似乎也确实意味着失去了人性特征);

  • 对于StatefulSet中的Pod,每个Pod挂载自己独立的存储,如果一个Pod出现故障,从其他节点启动一个同样名字的Pod,要挂载上原来Pod的存储继续以它的状态提供服务。

1.3.5. service

Kubernetes Service是个抽象化的概念,主要定义了逻辑上的一群Pod(带着相同标签、做类似事情的一群Pod)以及如何存取他们的规则。

Service作为中介层,避免使用者和Pod进行直接联机,除了让我们服务维持一定弹性能够选择不同的Pod来处理请求外,某种程度上亦避免裸露无谓的Port而导致信息安全问题。

对于使用者而言,仅须知道有人会处理他们的请求,而毋须知道实际上处理的人是谁。

[图片上传失败...(image-2a66e8-1564578806789)]

关于Service相关IP:

  • Pod IP:每个pod 都有独立的虚拟IP, 通过网络插件创建IP(如flannel),使跨主机的Pod可以互通
    
  • Cluster IP:是Service的内部IP,可以看成一个域名解析,解析最后发给哪个POD,可以用做内部POD访问服务。通过iptables规则访问服务。
    
  • External IP: 是Service的外部IP,对外提供给Client访问。
    

Pod IP 和 Cluster IP 都是kubernetes内部ip。

1.3.6. Label

Kubernetes中的任意API对象都是通过Label进行标识,Label的实质是一系列的Key/Value键值对,其中key于value由用户自己指定。

Label可以附加在各种资源对象上,如Node、Pod、Service、RC等,一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上去。

Label是Replication Controller和Service运行的基础,二者通过Label来进行关联Node上运行的Pod。

1.3.7. 存储卷(Volume)

Kubernetes集群中的存储卷跟Docker的存储卷有些类似,只不过Docker的存储卷作用范围为一个容器,而Kubernetes的存储卷的生命周期和作用范围是一个Pod。每个Pod中声明的存储卷由Pod中的所有容器共享。

Kubernetes支持非常多的存储卷类型,特别的,支持多种公有云平台的存储,包括AWS,Google和Azure云;
支持多种分布式存储包括GlusterFS和Ceph;也支持较容易使用的主机本地目录emptyDir, hostPath和NFS。
Kubernetes还支持使用Persistent Volume Claim即PVC这种逻辑存储,使用这种存储,使得存储的使用者可以忽略后台的实际存储技术(例如AWS,Google或GlusterFS和Ceph),而将有关存储实际技术的配置交给存储管理员通过Persistent Volume来配置。

持久存储卷(Persistent Volume,PV)和持久存储卷声明(Persistent Volume Claim,PVC
PV和PVC使得Kubernetes集群具备了存储的逻辑抽象能力,使得在配置Pod的逻辑里可以忽略对实际后台存储技术的配置,而把这项配置的工作交给PV的配置者,即集群的管理者。
存储的PV和PVC的这种关系,跟计算的Node和Pod的关系是非常类似的;
PV和Node是资源的提供者,根据集群的基础设施变化而变化,由Kubernetes集群管理员配置;
而PVC和Pod是资源的使用者,根据业务服务的需求变化而变化,有Kubernetes集群的使用者即服务的管理员来配置。

1.4. 使用yaml描述对象

1.4.1 YAML语法

kubernetes使用YAML写对象信息, YAML语法规则:

  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进时不允许使用Tal键,只允许使用空格
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • ”#” 表示注释,从这个字符一直到行尾,都会被解析器忽略

1.4.2 Pod, Service和Deployment

Kubernetes有三个你应该知道的对象类型:

  • Pods - 运行一个或多个密切相关的容器
  • Service - 在Kubernetes集群中建立网络
  • Deployment - 维护一组相同的pod,确保它们具有正确的配置并且存在正确的数量。

Pod:

  • 运行一组容器
  • 适合一次性开发目的
  • 很少直接用于生产

Deployment:

  • 运行一组相同的pod
  • 监视每个pod的状态,并根据需要进行更新
  • 对开发者有好处
  • 适合生产

尽量避免使用Pod并实施Deployments来管理容器作为类型的对象
Pod在节点故障或pod终止时不会被重新安排(或自我修复)。

1.4.3. 使用yaml描述对象

在 Kubernetes 系统中,Kubernetes 对象 是持久化的实体。Kubernetes 使用这些实体去表示整个集群的状态。特别地,它们描述了如下信息:

  • 哪些容器化应用在运行(以及在哪个 Node 上)
  • 可以被应用使用的资源
  • 关于应用运行时表现的策略,比如重启策略、升级策略,以及容错策略

可以简单的分类为以下几种资源对象:

类别 名称
资源对象 Pod、ReplicaSet、ReplicationController、Deployment、StatefulSet、DaemonSet、 Job、CronJob、 HorizontalPodAutoscaling、Node、Namespace、Service、 Ingress、Label、CustomResourceDefinition
存储对象 Volume、PersistentVolume、Secret、ConfigMap
策略对象 SecurityContext、ResourceQuota、LimitRange
身份对象 ServiceAccount、Role、ClusterRole

大多数情况下,需要在 .yaml 文件中为 kubectl 提供对象信息。

在想要创建的 Kubernetes 对象对应的 .yaml 文件中,需要配置如下的字段:

  • apiVersion - 创建该对象所使用的 Kubernetes API 的版本
  • kind - 想要创建的对象的类型
  • metadata - 帮助识别对象唯一性的数据,包括一个 name 字符串、UID 和可选的 namespace

这里有更多例子:

https://cheatsheet.dennyzhang.com/kubernetes-yaml-templates

下面是一些常用例子:

  • Endpoints

可以把外部的链接到k8s系统中,如下将一个mysql连接到k8s中。

kind: Endpoints
apiVersion: v1
metadata:
  name: mysql-production
  namespace: test
subsets:
  - addresses:
      - ip: 10.0.0.82    # 外部mysql ip
    ports:
      - port: 3306       # 外部mysql 端口
  • service

  apiVersion: v1
   kind: Service
   metadata:
     name: mysql-production
     namespace: test
   spec:
     ports:
       - port: 3306
# port: 3306为内部IP
name: mysql-production #为service名称
# 此时mysql-production.test即为mysql的虚拟IP,其他可配置该字段连接到mysql,例如
#   "java","-Dspring.datasource.url=jdbc:mysql://mysql-production.test:3306/config", "-jar", "xxx.jar"

1.4.2. pod配置例子

apiVersion: v1             #指定api版本,此值必须在kubectl apiversion中 
kind: Pod                  #指定创建资源的角色/类型 
metadata:                  #资源的元数据/属性 
  name: web04-pod          #资源的名字,在同一个namespace中必须唯一 
  labels:                  #设定资源的标签,详情请见http://blog.csdn.net/liyingke112/article/details/77482384
    k8s-app: apache 
    version: v1 
    kubernetes.io/cluster-service: "true" 
  annotations:             #自定义注解列表 
    - name: String         #自定义注解名字 
spec:#specification of the resource content 指定该资源的内容 
  restartPolicy: Always    #表明该容器一直运行,默认k8s的策略,在此容器退出后,会立即创建一个相同的容器 
  nodeSelector:            #节点选择,先给主机打标签kubectl label nodes kube-node1 zone=node1 
    zone: node1 
  containers: 
  - name: web04-pod        #容器的名字 
    image: web:apache      #容器使用的镜像地址 
    imagePullPolicy: Never #三个选择Always、Never、IfNotPresent,每次启动时检查和更新(从registery)images的策略,
                           # Always,每次都检查
                           # Never,每次都不检查(不管本地是否有)
                           # IfNotPresent,如果本地有就不检查,如果没有就拉取
    command: ['sh']        #启动容器的运行命令,将覆盖容器中的Entrypoint,对应Dockefile中的ENTRYPOINT 
    args: ["$(str)"]       #启动容器的命令参数,对应Dockerfile中CMD参数 
    env:                   #指定容器中的环境变量 
    - name: str            #变量的名字 
      value: "/etc/run.sh" #变量的值 
    resources:             #资源管理,请求请见http://blog.csdn.net/liyingke112/article/details/77452630
      requests:            #容器运行时,最低资源需求,也就是说最少需要多少资源容器才能正常运行 
        cpu: 0.1           #CPU资源(核数),两种方式,浮点数或者是整数+m,0.1=100m,最少值为0.001核(1m)
        memory: 32Mi       #内存使用量 
      limits:              #资源限制 
        cpu: 0.5 
        memory: 32Mi 
    ports: 
    - containerPort: 80    #容器开发对外的端口
      name: httpd          #名称
      protocol: TCP 
    livenessProbe:         #pod内容器健康检查的设置,详情请见http://blog.csdn.net/liyingke112/article/details/77531584
      httpGet:             #通过httpget检查健康,返回200-399之间,则认为容器正常 
        path: /            #URI地址 
        port: 80 
        #host: 127.0.0.1   #主机地址 
        scheme: HTTP 
      initialDelaySeconds: 180 #表明第一次检测在容器启动后多长时间后开始 
      timeoutSeconds: 5    #检测的超时时间 
      periodSeconds: 15    #检查间隔时间 
      #也可以用这种方法 
      #exec: 执行命令的方法进行监测,如果其退出码不为0,则认为容器正常 
      #  command: 
      #    - cat 
      #    - /tmp/health 
      #也可以用这种方法 
      #tcpSocket: //通过tcpSocket检查健康  
      #  port: number  
    lifecycle:             #生命周期管理 
      postStart:           #容器运行之前运行的任务 
        exec: 
          command: 
            - 'sh' 
            - 'yum upgrade -y' 
      preStop:             #容器关闭之前运行的任务 
        exec: 
          command: ['service httpd stop'] 
    volumeMounts:          #详情请见http://blog.csdn.net/liyingke112/article/details/76577520
    - name: volume         #挂载设备的名字,与volumes[*].name 需要对应   
      mountPath: /data     #挂载到容器的某个路径下 
      readOnly: True 
  volumes:                 #定义一组挂载设备 
  - name: volume           #定义一个挂载设备的名字 
    #meptyDir: {} 
    hostPath: 
      path: /opt           #挂载设备类型为hostPath,路径为宿主机下的/opt,这里设备类型支持很多种 

1.4.3. deployment

部署一个Pod,内部只能链接service,无法互相链接.

apiVersion: extensions/v1beta1   #接口版本
kind: Deployment                 #接口类型
metadata:
  name: cango-demo               #Deployment名称
  namespace: cango-prd           #命名空间
  labels:
    app: cango-demo              #标签
spec:
  replicas: 3
  strategy:
    rollingUpdate:  ##由于replicas为3,则整个升级,pod个数在2-4个之间
      maxSurge: 1      #滚动升级时会先启动1个pod
      maxUnavailable: 1 #滚动升级时允许的最大Unavailable的pod个数
  template:        
    metadata:
      labels:
        app: cango-demo  #模板名称必填
    sepc: #定义容器模板,该模板可以包含多个容器
      containers:                                                                  
        - name: cango-demo                                                           #镜像名称
          image: swr.cn-east-2.myhuaweicloud.com/cango-prd/cango-demo:0.0.1-SNAPSHOT #镜像地址
          command: [ "/bin/sh","-c","cat /etc/config/path/to/special-key" ]    #启动命令
          args:                                                                #启动参数
            - '-storage.local.retention=$(STORAGE_RETENTION)'
            - '-storage.local.memory-chunks=$(STORAGE_MEMORY_CHUNKS)'
            - '-config.file=/etc/prometheus/prometheus.yml'
            - '-alertmanager.url=http://alertmanager:9093/alertmanager'
            - '-web.external-url=$(EXTERNAL_URL)'
    #如果command和args均没有写,那么用Docker默认的配置。
    #如果command写了,但args没有写,那么Docker默认的配置会被忽略而且仅仅执行.yaml文件的command(不带任何参数的)。
    #如果command没写,但args写了,那么Docker默认配置的ENTRYPOINT的命令行会被执行,但是调用的参数是.yaml中的args。
    #如果如果command和args都写了,那么Docker默认的配置被忽略,使用.yaml的配置。
          imagePullPolicy: IfNotPresent  #如果不存在则拉取
          livenessProbe:       #表示container是否处于live状态。如果LivenessProbe失败,LivenessProbe将会通知kubelet对应的container不健康了。随后kubelet将kill掉container,并根据RestarPolicy进行进一步的操作。默认情况下LivenessProbe在第一次检测之前初始化值为Success,如果container没有提供LivenessProbe,则也认为是Success;
            httpGet:
              path: /health #如果没有心跳检测接口就为/
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 60 ##启动后延时多久开始运行检测
            timeoutSeconds: 5
            successThreshold: 1
            failureThreshold: 5
          readinessProbe:
            httpGet:
              path: /health #如果没有心跳检测接口就为/
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 30 ##启动后延时多久开始运行检测
            timeoutSeconds: 5
            successThreshold: 1
            failureThreshold: 5
          resources:              ##CPU内存限制
            requests:
              cpu: 2
              memory: 2048Mi
            limits:
              cpu: 2
              memory: 2048Mi
          env:                    ##通过环境变量的方式,直接传递pod=自定义Linux OS环境变量
            - name: LOCAL_KEY     #本地Key
              value: value
            - name: CONFIG_MAP_KEY  #局策略可使用configMap的配置Key,
              valueFrom:
                configMapKeyRef:
                  name: special-config   #configmap中找到name为special-config
                  key: special.type      #找到name为special-config里data下的key
          ports:
            - name: http
              containerPort: 8080 #对service暴露端口
          volumeMounts:     #挂载volumes中定义的磁盘
          - name: log-cache
            mount: /tmp/log
          - name: sdb       #普通用法,该卷跟随容器销毁,挂载一个目录
            mountPath: /data/media   
          - name: nfs-client-root    #直接挂载硬盘方法,如挂载下面的nfs目录到/mnt/nfs
            mountPath: /mnt/nfs
          - name: example-volume-config  #高级用法第1种,将ConfigMap的log-script,backup-script分别挂载到/etc/config目录下的一个相对路径path/to/...下,如果存在同名文件,直接覆盖。
            mountPath: /etc/config      
          - name: rbd-pvc                #高级用法第2中,挂载PVC(PresistentVolumeClaim)
  
#使用volume将ConfigMap作为文件或目录直接挂载,其中每一个key-value键值对都会生成一个文件,key为文件名,value为内容,
  volumes:  # 定义磁盘给上面volumeMounts挂载
  - name: log-cache
    emptyDir: {}
  - name: sdb  #挂载宿主机上面的目录
    hostPath:
      path: /any/path/it/will/be/replaced
  - name: example-volume-config  # 供ConfigMap文件内容到指定路径使用
    configMap:
      name: example-volume-config  #ConfigMap中名称
      items:
      - key: log-script           #ConfigMap中的Key
        path: path/to/log-script  #指定目录下的一个相对路径path/to/log-script
      - key: backup-script        #ConfigMap中的Key
        path: path/to/backup-script  #指定目录下的一个相对路径path/to/backup-script
  - name: nfs-client-root         #供挂载NFS存储类型
    nfs:
      server: 10.42.0.55          #NFS服务器地址
      path: /opt/public           #showmount -e 看一下路径
  - name: rbd-pvc                 #挂载PVC磁盘
    persistentVolumeClaim:
      claimName: rbd-pvc1         #挂载已经申请的pvc磁盘

1.4.4. Service

部署一个内部虚拟IP,其他deployment可以链接。

apiVersion: v1
kind: Service
matadata:                                #元数据
  name: string                           #service的名称
  namespace: string                      #命名空间 
  labels:                                #自定义标签属性列表
    - name: string
  annotations:                           #自定义注解属性列表 
    - name: string
spec:                                    #详细描述
  selector: []                           #label selector配置,将选择具有label标签的Pod作为管理
                                         #范围
  type: string                           #service的类型,指定service的访问方式,默认为
                                         #clusterIp
  clusterIP: string                      #虚拟服务地址     
  sessionAffinity: string                #是否支持session
  ports:                                 #service需要暴露的端口列表
  - name: string                         #端口名称
    protocol: string                     #端口协议,支持TCP和UDP,默认TCP
    port: int                            #服务监听的端口号
    targetPort: int                      #需要转发到后端Pod的端口号
    nodePort: int                        #当type = NodePort时,指定映射到物理机的端口号
  status:                                #当spce.type=LoadBalancer时,设置外部负载均衡器的地址
    loadBalancer:                        #外部负载均衡器   
      ingress:                           #外部负载均衡器
        ip: string                       #外部负载均衡器的Ip地址值
        hostname: string                 #外部负载均衡器的主机

1.4.5. ingress

你可以给Ingress配置提供外部可访问的URL、负载均衡、SSL、基于名称的虚拟主机等。用户通过POST Ingress资源到API server的方式来请求ingress。 Ingress controller负责实现Ingress,通常使用负载平衡器,它还可以配置边界路由和其他前端,这有助于以HA方式处理流量。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
spec:                                # Ingress spec 中包含配置一个loadbalancer或proxy server
  rules:                             # 的所有信息。最重要的是,它包含了一个匹配所有入站请求的规
  - http:                            # 则列表。目前ingress只支持http规则。
      paths:
      - path: /testpath              # 每条http规则包含以下信息:一个host配置项(比如
                                     # for.bar.com,在这个例子中默认是*),path列表(比
                                     # 如:/testpath),每个path都关联一个backend(比如
                                     # test:80)。在loadbalancer将流量转发到backend之前,所有的
                                     # 入站请求都要先匹配host和path。
       backend:                       
          serviceName: test          # backend是一个service:port的组合。Ingress的流量被转发到                       
          servicePort: 80            #  它所匹配的backend

1.5. kubernetes其他功能介绍

configmaps: 为了让应用程序可以方便转移或避免重新编译image,因此会将配置与应用程序解构,以单独的ConfigMap配置.

永久性存储Persistent Volume: Pod 里面指定mountPath和 type.

1.6. kubernetes第三方工具

Jaeger是一个开源的分布式跟踪Trace系统,可以用来trace每个客户端送出的请求,进而找出执行过程的问题.

Helm是一个可以安装与管理Kubernetes应用程序的工具,我们可以将Helm视为是Kubernetes的package manager.

普罗米修斯(Prometheus)是一个可以提供Kubernetes应用程序测量的开源套件,一方面可以汇整测量信息,也可以提供警告(Alert)通知.

Deployment通常是首选,因为它定义了ReplicaSet以确保所需数量的Pod始终可用,并指定替换Pod的策略,例如RollingUpdate。

1.7. kubernetes网络

Kubernetes本身并不提供网络功能,只是把网络接口开放出来,通过插件的形式实现。
Kubernetes中的网络要解决的核心问题就是每台主机的IP地址网段划分,以及单个容器的IP地址分配。概括为:

  • 保证每个Pod拥有一个集群内唯一的IP地址
  • 保证不同节点的IP地址划分不会重复
  • 保证跨节点的Pod可以互相通信
  • 保证不同节点的Pod可以与跨节点的主机互相通信

为了解决该问题,出现了一系列开源的Kubernetes中的网络插件与方案,如:

  • flannel
  • calico
  • contiv
  • weave net
  • kube-router
  • cilium
  • canal

[图片上传失败...(image-d50565-1564578806789)]

1.7.1. flannel网络

Flannel是作为一个二进制文件的方式部署在每个node上,主要实现两个功能:

  • 为每个node分配subnet,容器将自动从该子网中获取IP地址
  • 当有node加入到网络中时,为每个node增加路由配置

下面是flannel网络的运行模式:

[图片上传失败...(image-6afe01-1564578806789)]

Flannel首先创建了一个名为flannel0的网桥,而且这个网桥的一端连接docker0的网桥,另一端连接一个名为flanneld的服务进程。

Flanneld进程并不简单,它首先上连etcd,利用etcd来管理可分配的IP地址段资源,同时监控etcd中每个Pod的实际地址,并在内存中建立了一个Pod节点路由表;然后下连docker0和物理网络,使用内存中的Pod节点路由表,将docker0发给它的数据包包装起来,利用物理网络的连接将数据包投递到目标flanneld上,从而完成pod到pod之间的直接的地址通信。

Flannel之间的底层通信协议的可选余地有很多,比如UDP、VXlan、AWS VPC等等。只要能通到对端的Flannel就可以了。源Flannel封包,目标Flannel解包,最终docker0看到的就是原始的数据,非常透明,根本感觉不到中间Flannel的存在。

  • 数据从源容器中发出后,经由所在主机的docker0虚拟网卡转发到flannel0虚拟网卡,这是个P2P的虚拟网卡,flanneld服务监听在网卡的另外一端。
  • Flannel通过Etcd服务维护了一张节点间的路由表。
  • 源主机的flanneld服务将原本的数据内容UDP封装后根据自己的路由表投递给目的节点的flanneld服务,数据到达以后被解包,然后直接进入目的节点的flannel0虚拟网卡,
    然后被转发到目的主机的docker0虚拟网卡,最后就像本机容器通信一下的有docker0路由到达目标容器。

总结:

    1. 基于 UDP 的 flannel 网络模型具有简单易用,不依赖底层网络的特点
    1. 性能和时延问题。
      Flannel实现了对Kubernetes网络的支持,但是它引入了多个网络组件,在网络通信时需要转到flannel0网络接口,再转到用户态的flanneld程序,到对端后还需要走这个过程的反过程,所以也会引入一些网络的时延损耗。另外Flannel默认的底层通信协议是UDP。UDP本身是非可靠协议,虽然两端的TCP实现了可靠传输,但在大流量、高并发应用场景下还需要反复调试,确保不会出现传输质量的问题。特别是对网络依赖重的应用,需要评估对业务的影响。

1.7.2. Calico

Calico创建和管理一个扁平的三层网络(不需要overlay),每个容器会分配一个可路由的IP。由于通信时不需要解包和封包,网络性能损耗小,易于排查,且易于水平扩展。

小规模部署时可以通过BGP client直接互联,大规模下可通过指定的BGP Route Reflector来完成,这样保证所有的数据流量都是通过IP路由的方式完成互联的。

Calico基于iptables还提供了丰富而灵活的网络Policy,保证通过各个节点上的ACL来提供Workload的多租户隔离、安全组以及其他可达性限制等功能。
[图片上传失败...(image-2dd999-1564578806789)]

Calico主要由Felix、etcd、BGP client、BGP Route Reflector组成。

  • Etcd:负责存储网络信息
  • BGP client:负责将Felix配置的路由信息分发到其他节点
  • Felix:Calico Agent,每个节点都需要运行,主要负责配置路由、配置ACLs、报告状态
  • BGP Route Reflector:大规模部署时需要用到,作为BGP client的中心连接点,可以避免每个节点互联

1.8. 云上的kubernetes

在 Kubernetes 出现之前,就已经有人提出了云原生的概念,如 2010 年 Paul Fremantle 就在他的博客中提出了云原生的核心理念,但是还没有切实的技术解决方案。

而那时候 PaaS 才刚刚出现,PaaS 平台提供商 Heroku 提出了 12 因素应用的理念,为构建 SaaS 应用提供了方法论,该理念在云原生时代依然适用。

现如今云已经可以为我们提供稳定而唾手可得的基础设施,但是业务上云成了一个难题,Kubernetes 的出现与其说是从最初的容器编排解决方案开始,倒不如说是为了解决应用上云(即云原生应用)这个难题。

Kubernetes 作为云应用的部署标准,直接面向业务应用,大大提高了云应用的可移植性,解决云厂商锁定的问题,让云应用可以在夸云之间无缝迁移,甚至用来管理混合云,成为企业 IT 云平台的新标准。

1.8.1 AKS 介绍

微软的Azure Kubernetes Service以下简称AKS,提供简单的部署,管理与操作界面,具有以下的几个特点:

  • 订阅者不必担心升级与修正问题,AKS提供自动更新与修正
  • AKS服务具有高可用度与高可靠性
  • AKS可以透过命令或UI简单的调整扩充
  • AKS具有自我修复能力
  • AKS提供API Server监控机制
  • AKS可以透过Azure AD以及Role Base Access Control(RBAC)控管丛集的存取安全性
  • AKS服务的Azure托管的管理控制平台(Control plane/Master nodes)提供免费使用
    这边要特别说明,AKS管理控制平台是由微软托管的,订阅者不需要设定Master nodes,订阅的使用者透过Kubernetes API endpoint,使用命令(Azure Cli - az aks)来管理AKS.
    [图片上传失败...(image-29c9fc-1564578806789)]

2. Centos7安装

安装可以分成3个部分:

配置系统参数,例如使用不同的hostname , 禁止swap和 selinux,允许防火墙通过某些端口等等
在所有节点上安装docker
在所有节点上安装kubernetes
配置主节点
在worker节点上向主节点注册自己。
下面将分别介绍。

2.1. 配置系统参数

2.1.1. 每个机器使用不同的主机名

在每台机器上运行:

hostnamectl set-hostname new-hostname
如果没有自己的 DNS 服务器,那么需要修改所有机器的 /etc/hosts 文件,把kuberntes内所有主机名(master 和 worker node )和ip的对应添加进来, 例如:

192.168.1.30 k8s-master
192.168.1.40 worker-node1
192.168.1.50 worker-node2

2.1.2. 关闭selinux

setenforce 0 #实时动态关闭 selinux
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config #禁止重启后自动开启

2.1.3. 关闭swap

swapoff -a #实时动态关闭交换分区
sed -i '/ swap / s/^/#/' /etc/fstab #禁止重启后自动开启

2.1.4. 配置网络防火墙

简单一些的办法是直接禁止:

systemctl disable firewalld && systemctl stop firewalld

复杂点是开放 kubernetes 需要的端口,下面是master node:

firewall-cmd --permanent --add-port=6443/tcp
firewall-cmd --permanent --add-port=2379-2380/tcp
firewall-cmd --permanent --add-port=10250/tcp
firewall-cmd --permanent --add-port=10251/tcp
firewall-cmd --permanent --add-port=10252/tcp
firewall-cmd --permanent --add-port=10255/tcp
firewall-cmd --reload

worker node:

firewall-cmd --permanent --add-port=10250/tcp
firewall-cmd --permanent --add-port=10255/tcp
firewall-cmd --permanent --add-port=30000-32767/tcp
firewall-cmd --permanent --add-port=6783/tcp
firewall-cmd  --reload

2.1.5. 配置网络参数

cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
vm.swappiness=0
EOF
 
modprobe br_netfilter  #执行该命令 如果不执行就会在应用k8s.conf时出现加载错误
sysctl -p /etc/sysctl.d/k8s.conf #应用配置文件

2.2. 安装docker
kuberntes 使用docker作为pod 的运行基础。 CentOS7.6 自带的 docker 是支持kubernetes的。通过下面命令安装。

sudo yum install -y docker
sudo systemctl enable docker && sudo systemctl start docker

如果需要也可以使用最新的 docker-ce:

2.3. 安装kubernetes

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
        https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
yum install -y kubelet kubeadm kubectl
systemctl enable kubelet && systemctl start kubelet

如果上不了谷歌,那么根据这个下载image和yum安装

# https://blog.csdn.net/jb19900111/article/details/88884848
[root@k8smaster ~]# cat getk8s_images.sh 
#!/bin/bash
images=(
kube-apiserver:v1.14.0
kube-controller-manager:v1.14.0
kube-scheduler:v1.14.0
kube-proxy:v1.14.0
pause:3.1
etcd:3.3.10
coredns:1.3.1
kubernetes-dashboard-amd64:v1.10.0
heapster-amd64:v1.5.4
heapster-grafana-amd64:v5.0.4
heapster-influxdb-amd64:v1.5.2
pause-amd64:3.1
)

for imageName in ${images[@]} ; do
    docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
    docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName
done
[root@k8smaster ~]# sh -x  getk8s_images.sh

[root@k8smaster ~]# cat /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
        http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg

[root@k8smaster ~]# yum -y install  kubelet kubeadm kubectl --disableexcludes=kubernetes

2.4. 配置主节点(master node)

确认一下docker 已经使用 systemd:

docker info | grep -i cgroup

会显示 "Cgroup Driver: systemd", 如果不是那需要修改

在master节点上运行:

kubeadm init --apiserver-advertise-address=192.168.1.30 --pod-network-cidr=10.244.0.0/16

其中:

--apiserver-advertise-address 指定master 节点的ip地址。如果 master 节点只有一个ip, 可以忽略这个参数。

--pod-network-cidr=10.244.0.0/16 指定pod网络地址范围, 10.244.0.0/16 是 flannel 网络的IP地址范围,如果想使用其他网络类型,那么根据它的介绍设置参数。

命令执行后会有提示,根据提示执行:

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

还有安装网络的提示:

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml

OK, 现在 master 安装好了。

上面命令还有一个重要提示,就是worker node注册命令, 把这个命令保存下来备用:

sudo kubeadm join 192.168.0.120:6443 --token khm95w.mo0wwenu2o9hglls \
    --discovery-token-ca-cert-hash sha256:aeb0ca593b63c8d674719858fd2397825825cebc552e3c165f00edb9671d6e32

可以选装 dashboard, master 上执行下面安装:

#kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
kubectl apply -f  https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

2.5. 工作节点(worker node)注册

在worker node 执行上面"kubeadm init "产生的注册命令,就可以成功添加worker node到 master node:

sudo kubeadm join 192.168.0.120:6443 --token khm95w.mo0wwenu2o9hglls \
    --discovery-token-ca-cert-hash sha256:aeb0ca593b63c8d674719858fd2397825825cebc552e3c165f00edb9671d6e32

2.6. 验证和调试

所有的kubernetes 状态和配置都可以通过 kubectl获取,但是这个命令仅能在master node上执行。

2.6.1. 查看状态

下面查看状态:

kubectl get nodes
kubectl get pods --all-namespaces

2.6.2. 创建一个pod和服务

创建pod 和服务有两种方法:

直接kubectl 命令行创建
在yaml 里面定义,然后调用 kubectl apply -f 创建
下面是命令行创建方法:

[root@k8smaster ~]# kubectl create deployment nginx --image=nginx
deployment.apps/nginx created
[root@k8smaster ~]# kubectl describe deployment nginx
Name:                   nginx
Namespace:              default
CreationTimestamp:      Fri, 07 Jun 2019 23:24:06 -0400
Labels:                 app=nginx
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=nginx
Replicas:               1 desired | 1 updated | 1 total | 0 available | 1 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx
    Port:         <none>
    Host Port:    <none>
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      False   MinimumReplicasUnavailable
  Progressing    True    ReplicaSetUpdated
OldReplicaSets:  <none>
NewReplicaSet:   nginx-65f88748fd (1/1 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  10s   deployment-controller  Scaled up replica set nginx-65f88748fd to 1
[root@k8smaster ~]# kubectl create service nodeport nginx --tcp=80:80
service/nginx created
[root@k8smaster ~]# kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-65f88748fd-kjjdk   1/1     Running   0          44s
[root@k8smaster ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP        39h
nginx        NodePort    10.109.182.154   <none>        80:32303/TCP   13s

访问新建的service:

[root@k8smaster ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP        39h
nginx        NodePort    10.109.182.154   <none>        80:32303/TCP   13s
[root@k8smaster ~]# kubectl get nodes
NAME        STATUS   ROLES    AGE   VERSION
k8smaster   Ready    master   39h   v1.14.2
k8snode1    Ready    <none>   39h   v1.14.2
[root@k8smaster ~]# curl k8snode1:32303
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
 
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
 
<p><em>Thank you for using nginx.</em></p>
</body>
</html>

还可以访问 master node/ 或是 svr 运行的 worker node 的 svr 开放端口:

附nginx 的service 和 deployment 编写方法,
通过
kubectl create -f nginx.yaml
创建
通过:
kubectl delete -f nginx.yaml
删除


[root@k8smaster ~]# cat nginx.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  ports:
  - port: 8000 # the port that this service should serve on
    # the container on each pod to connect to, can be a name
    # (e.g. 'www') or a number (e.g. 80)
    targetPort: 80
    protocol: TCP
  # just like the selector in the deployment,
  # but this time it identifies the set of pods to load balance
  # traffic to.
  selector:
    app: nginx
  type: LoadBalancer

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: 10.206.138.106:5000/nginx:latest
        resources:
          limits:
            memory: "128Mi"
            cpu: "250m"
        ports:
        - containerPort: 80
      imagePullSecrets:
        - name: vmireposec
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容