Docker
Docker的概念
Docker 是 一个打包、 分发和运行应用程序的平台。 它允许将你 的应用程序和应用程序所依赖的整个环境打包在一起。 这既可以是一些应用程序需 要的库, 也可以是一个被安装的操作系统所有可用的文件。
- 镜像:Docker镜像里包含了你打包的应用程序及其所依赖的环境,它包含应用程序可用的文件系统和其他元数据,如镜像运行时的可执行文件路径。
- 镜像仓库:Docker镜像仓库用于存放Docker镜像,以及促进不同人和不同电脑之间共享这些镜像。
- 容器:Docker容器通常是一个Linux容器,它基于Docker镜像被创建,一个运行中的容器是一个运行在Docker主机上的进程,但它和主机,以及所有运行在主机上的其他进程都是隔离的,这些进程也是资源受限的,意味着它只能访问和使用分配给它的资源。
容器隔离机制
- Linux命名空间,它使每个进程只看到自己的系统视图(文件、进程、网络接口、主机名等)
- Linux控制组(cgroups):它限制了进程能使用的资源量(CPU、内存、网络带宽等)
Docker核心组件
- Docker客户端和服务器,也称为Docker引擎
- Docker镜像
- Registry
- Docker容器
Docker技术组件
- 一个原生的Linux容器格式,Docker中称为libcontainer
- Linux内核的命名空间(namespace),用于隔离文件系统、进程和网络
- 文件系统隔离:每个容器都有自己的root文件系统
- 进程隔离:每个容器都运行在自己的进程环境中
- 网络隔离:容器间的虚拟网络接口和IP地址都是分开的
- 资源隔离和分组:使用cgroups将CPU和内存之类的资源独立分配给每个Docker容器
- 写时复制:文件系统都是通过写时复制创建的,这就意味着文件系统时分层的、快速的、而且占用的磁盘空间更小
- 日志:容器产生的STDOUT、STDERR和STDIN这些IO流都会被收集并计入日志,用来进行日志分析和故障拍错
- 交互式shell:用户可以创建一个伪tty终端,将其连接到STDIN,为容器提供一个交互式的shell
构建、分发和运行Docker镜像
Docker Hello-world
1 | docker search "hello-world" #搜索一个名为 hello-world的镜像 |
Docker搭建应用
应用包含一个名为app.js
的文件,代码如下
1 | const http = require ('http'); |
为镜像创建Dockerfile,在app.js
同目录下,创建一个Dockerfile文件,内容如下
1 | FROM node:7 #构建所基于的基础镜像 |
构建容器镜像,以下命令告诉Docker需要基于当前目录构建一个叫kubia的镜像
1 | docker build -t kubia . |
基于Dockerfile构建一个新的容器镜像具体流程如下图所示
运行容器镜像,下面这条命令告知Docker基于kubia镜像创建一个叫kubia- container的新容器,这个容器与命令行分离,意味着在后台运行,本机上的8080端口会被映射到容器内的8080端口,所以可以通过localhost:8080
来访问这个应用,
1 | docker run --name kubia-container -p 8080:8080 -d kubia |
访问应用,发现应用把934fe4c0ca9c
作为主机名返回,这个十六进制数就是Docker容器的ID
1 | curl localhost:8080 |
假如说这个时候我们删除了一个容器id想要恢复的话可以使用docker start命令
在已有的容器内部运行shell
这条命令会在已有的kubia-container容器内部运行bash,bash进行会和主容器进程拥有相同的命名空间,这样可以从内部探索容器。
- -i,确保标准输入流保待开放。需要在 shell 中输入命令。
- -t,分配 一 个伪终端(TTY)。
1 | docker exec -it kubia-container bash |
停止容器
1 | docker stop kubia-container |
删除容器
1 | docker rm kubia-container |
向镜像仓库推送镜像
1 | docker tag kubia xxx/kubia #xxx是自己的Docker Hub ID |
在不同机器上运行镜像
1 | docker run -p 8080:8080 -d xxx/kubia |
Docker持续集成
为了演示Docker持续集成的能力,我们将使用Jenkins CI构建一个测试流水线,首先会构建一个运行Docker的Jenkins服务器,一旦Jenkins运行起来,将展示最基础的单容器测试运行,最后将展示多容器的测试场景。
Jenkins教程:https://www.jenkins.io/zh/doc/
构建Jenkins和Docker服务器
第一步先准备一个文件夹
1 | mkdir jenkins && cd jenkins |
在jenkins目录中,制作Dockerfile
1 | FROM jenkins/jenkins:lts |
构建镜像
我起的镜像名为elssm/dockerjenkins
,大家可以随意起名。
1 | caoyifan@MacBookPro jenkins % docker build -t elssm/dockerjenkins . |
构建好镜像之后启动镜像创建容器
1 | docker run -p 8080:8080 --name jenkins --privileged -d elssm/dockerjenkins |
其中--privileged
标志可以启动Docker的特权模式,这种模式允许我们以其宿主机的所有能力来运行容器,包括一些内核特性和设备访问。
这样容器jenkins就启动了,我们可以看一下启动后的日志
1 | caoyifan@MacBookPro jenkins % docker logs jenkins |
现在我们就可以通过本地的8080端口在浏览器中访问了,我这边打开之后发现是锁定的状态(大家的情况应该和我一样),如下图所示。因此需要输入密码解锁,密码路径已经告诉了我们。
进入jenkins容器
1 | docker exec -it jenkins bash |
获取密码
1 | cat var/jenkins_home/secrets/initialAdminPassword |
进行一部分简单的设置之后我们就可以进入Jenkins的登陆页面了,输入用户名和密码,如果是默认的话用户名就是admin
,密码就是上面cat
拿到的密码。输入之后就进入主界面了,如下图所示。
创建新的Jenkins作业
现在Jenkins服务器已经运行,我们可以来创建一个Jenkins作业。具体操作如下
将新作业命名为Docker_test_job
,作业类型为Freestyle project
。
接下来填写作业描述,在高级项目选项中选择Use Custom workspace
,并指定/tmp/jenkins-buildenv/${JOB_NAME}/workspace
作为目录。
在Source Code Management
区域,选择Git
并指定测试仓库为https://github.com/turnbullpress/docker-jenkins-sample.git
,该仓库包含了一些基于Ruby的RSpec测试
接下来下拉,找到Build
选项,单击Add Build Step
按钮增加一个构建的步骤,选择Execute shell
,如下图所示。
之后使用定义的脚本来启动和测试Docker,该脚本代码如下
1 | Build the image to be used for this run. |
那么上面的脚本具体做了些什么呢?首先它将使用包含刚刚指定的Git仓库的Dockerfile创建一个新的Docker镜像,这个Dockerfile提供了想要执行的测试环境。该Dockerfile代码如下
1 | FROM ubuntu:16.04 |
可以看到,Dockerfile构建了一个Ubuntu宿主机,安装了Ruby和RubyGems,之后安装了两个gem:rspec和ci_reporter_rspec。这样构建的镜像可以用于测试典型的基于Ruby且使用RSpec测试框架的应用程序。ci_reporter_rspec gem会把RSpec的输出转换为JUnit格式的XML输出,并交给Jenkins做解析。
回到之前的脚本,构建镜像之后,会创建一个包含Jenkins的工作空间的目录,会把这个目录挂载到Docker容器,并在这个目录里执行测试。然后我们从这个惊喜那个创建了容器,并且运行了测试,在容器里,把工作空间挂载到/opt/project
目录,之后执行命令切换到这个目录,并执行rake spec来运行RSpec测试。容器启动之后,我们拿到了容器的ID。
现在使用docker attach
命令进入容器,得到容器执行时输出的内容,然后使用docker wait
命令,docker wait
命令会一直阻塞,直到容器里的命令执行完成才会返回容器退出时的返回码,变量RC捕捉到容器退出时的返回码,最后,清理环境,删除刚刚创建的容器,并使用容器的返回码退出,这个返回码应该就是测试执行结果的返回码,Jenkins依赖这个返回码得知作业的测试结果时成功还是失败。对上面脚本的解释就到这里,让我们再回到Jenkins构建作业的步骤!!!
接下来,单机Add post-build action
,加入一个Publish JUint test result report
的动作,在Test report XMLs
域,需要指定spec/reports/*.xml
,这个目录是ci_reporter gem
的XML输出的位置,找到这个目录会让jenkins处理测试的历史结果和输出结果。
最后点击保存即可。
运行Jenkins作业
点击Build Now
即可。
遇到的问题
好家伙!我以为点击完Build Now
之后就会顺利的看到结果,万万没想到出现了各种各样的错误
报错如下
1 | ERROR: Step ‘Publish JUnit test result report’ failed: Test reports were found but none of them are new. Did leafNodes run? |
修改如下
在执行shell命令中添加如下代码,目的是不断更新这个文件的时间
1 | sleep 3 |
报错如下
1 | Cannot connect to the Docker daemon at unix:/var/run/docker.sock. Is the docker daemon running? |
修改如下
1 | sudo dockerd |
报错如下
1 | gnutls_handshake() failed: The TLS connection was non-properly terminated. |
修改如下
1 | git config --global --unset https.https://github.com.proxy |
报错如下
1 | [Checks API] No suitable checks publisher found |
修改如下
暂时没有找到修改方法。。。心态崩了
如下图是我Build
的心路历程,到最后也没有看到那一抹绿!!!
最终我的执行结果如下
1 | Started by user admin |
Docker进阶
Docker容器数据卷
需求:容器的持久化和同步操作,容器间也是可以数据共享的
容器之间可以有一个数据共享的技术,Docker容器中产生的数据同步到本地
将我们容器内的目录,挂载到linux上面
具名和匿名挂载
匿名:在
-v
只写了容器内的路径,没有写容器外的路径具名:通过
-v
卷名:容器内路径指定路径挂载:
-v
/宿主机路径:容器内路径DockerFile
用来构建docker镜像的构建文件,命令脚本
1
2
3
4
5
6
7
8创建dockerfile文件
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "----end----"
CMD /bin/bash1
2构建称为一个镜像
docker build -f dockerfile -t elssm/centos .1
2运行镜像
docker run1
2发布镜像
docker pushDockerFile:构建文件,定义了一切的步骤,源代码
DockerImages:通过DockerFile构建生成的镜像,最终发布和运行
Docker容器:容器就是镜像运行起来提供服务的
DockerFile的指令解析
1
2
3
4
5
6
7
8
9
10
11
12FROM #基础镜像,一切从这里开始构建
MAINTAINER #镜像是谁写的,姓名+邮箱
RUN #镜像构建的时候需要运行的命令
ADD #步骤,添加内容
WORKDIR #镜像的工作目录
VOLUME #挂载的目录
EXPOSE #指定暴露端口
CMD #指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT #指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD #当构建一个被继承DockerFile这个时候就会运行ONBUILD的指令
COPY:#类似ADD,将我们文件拷贝到镜像中
ENV #构建的时候设置环境变量创建一个自己的centos
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22编写Dockerfile的文件
FROM centos
MAINTAINER elssm<329847986@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash
通过这个文件构建镜像
docker build -f dockerfile -t name:0.1 .
测试运行
docker run -it image实战Tomcat镜像
准备镜像文件tomcat压缩包,jdk的压缩包
编写dockerfile文件
数据卷容器
1
2容器间数据同步
-- volumes -fromDocker网络
原理:我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0,桥接模式,使用的技术是veth-pair技术
veth-pair:就是一对虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连,正因为有这个特性,veth-pair充当一个桥梁,连接各种虚拟 网络设备
1
2
3
4
5查看docker下的所有network
docker network ls
查看详细信息
docker network inspect bridge_ID--link
可以解决docker下网络联通问题1
2
3
4
5
6
7
8
9
10
11
12下载tomcat镜像
docker pull tomcat
docker下启动两个tomcat
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat02 tomcat
启动tomcat03并绑定tomcat02
docker run -d -P --name tomcat03 --link tomcat02 tomcat
进入tomcat03并查看tomcat03配置文件
docker exec -it tomcat03 cat /etc/hosts自定义网络
查看所有的docker网络
1
docker network ls
网络模式
- bridge:桥接模式
- none:不配置网络
- host:和宿主机共享网络
- container:容器内网络连通
1
2
3
4
5
6
7
8我们可以自定义一个网络
--driver bridge
--subnet 192.168.0.0/16
--gateway 192.168.0.1
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
查看自己创建的网络
docker network inspect mynet自定义的网络docker都已经帮我们维护好了对应的关系
不同的集群使用不同的网络,保证集群是安全和健康的
网络连通
1
2
3
4
5测试打通tomcat01 - mynet
docker network connect mynet tomcat01
连通之后就是将tomcat01放到了mynet网络下
一个容器两个ip地址
Docker构建应用
第一个应用是使用Jekyll框架的自定义网站,我们会构建两个镜像
- 一个镜像安装了Jekyll及其他用于构建Jekyll网站的必要的软件
- 一个镜像通过Apache来让Jekyll网站工作起来
首先构建Jekyll基础镜像,本地创建Jekyll工作目录。
1 | mkdir jekyll && cd jekyll |
Dockerfile文件如下。镜像基于Ubuntu18.04,并且安装了Ruby和用于支持Jekyll的包,然后使用VOLUME指定创建了两个卷。将工作目录设置到/data/
,并通过ENTRYPOINT指定自动构建的命令。
1 | FROM ubuntu:18.04 |
构建Jekyll基础镜像
1 | docker build -t elssm/jekyll . |
接下来构建第二个镜像,一个用来架构新网站的Apache服务器,本地创建Apache工作目录。
1 | mkdir apache && cd apache |
Dockerfile文件如下
1 | FROM ubuntu:18.04 |
构建Jekyll Apache镜像
1 | docker build -t elssm/apache . |
启动Jekyll网站
启动之前先在本地准备一些博客的源代码,代码地址为https://github.com/turnbullpress/james_blog
我将源代码放在我的用户目录下,源代码重命名为elssm_blog
,下载好之后执行下面命令,这段命令启动了一个叫做elssm_blog的新容器,把我本地的elssm_blog
目录作为/data/
卷挂载到容器里,容器已经拿到网站的源代码,并将其构建到已编译的网站,存放到/var/www/html/
目录。
1 | caoyifan@MacBookPro ~ % docker run -v ~/elssm_blog:/data/ --name elssm_blog elssm/jekyll |
如果想在另一个容器里使用/var/www/html/
卷里编译好的网站,可以创建一个新的链接到这个卷的容器,如下命令。其中--volumes-from
标志把指定容器里的所有卷都加入新创建的容器里,这意味着Apache容器可以让问之前创建的elssm_blog容器里/var/www/html
卷中存放的编译好的Jekyll网站,即便elssm_blog容器没有运行,Apache容器也可以访问这个卷,前提是容器本身必须存在。
1 | docker run -d -P --volumes-from elssm_blog elssm/apache |
接下来我们查看一下容器把80端口映射到本本地哪个端口
1 | caoyifan@MacBookPro ~ % docker port 4d91e0f44a9a 80 |
通过打开localhost:55000
浏览该网站。
更新Jekyll网站
我们试着修改本地源代码中的_config.yml
文件,将title域改为ELSSM's Blog
。
接着更新网站
1 | docker start elssm_blog |
查看一下容器的日志,发现Jekyll编译过程第二次被运行,并且网站已经被更新。
1 | caoyifan@MacBookPro elssm_blog % docker logs elssm_blog |
再次刷新查看网站。由于共享的卷会自动更新,这一切都不需要更新或者重启Apache容器。
Kubernetes
发展历程
Infrastructure as a Service(阿里云)
Platform as a service(新浪云)
Software as a Service(Office 365)
资源管理器
- Apache MESOS
- docker SWARM
- Kubernetes
- 轻量级
- 开源
- 弹性伸缩
- 负载均衡
Kubernetes简介
Kubernetes是一个软件系统,它允许你在其上很容易地部署和管理容器化的应用。 它依赖于Linux容器的特性来运行异构应用, 而无须知道这些应用的内部详情, 也不需要手动将这些应用部署到每台机器。
Kubernetes 使你在数以千计的电脑节点上运行软件时就像所有这些节点是单个大节点一样。它将底层基础设施抽象,这样做同时简化了应用的开发、部署,以及对开发和运维团队的管理。
Kubernetes核心功能
如下图为一个最简单的Kubernetes系统图。整个系统由一个主节点和若干个工作节点组成 。 开发者把一个应用列表提交到主节点, Kubemetes 会将它们部署到集群的工作节点。组件被部署在哪个节点对于开发者和系统管理员来说都不用关心。除此之外,开发者还能指定一些应用必须一起运行,这样Kubernetes将会在一个工作节点上部署它们,而其他的将被分散部署到集群中。不管怎样部署,它们都能以相同的方式互相通信。
Kubernetes集群架构
在硬件级别,一个Kubernetes集群由很多节点组成,这些节点被分成以下两种类型
- 主节点:它承载着Kubernetes控制和管理整个集群系统的控制面板
- Kubernates API服务器:其他控制面板组件都要和它进行通信
- Scheculer:调度你的应用(为应用的每个可部署组件分配一个工作节点)
- Controller Manager:执行集群级别的功能,如复制组件、持续跟踪工作节点、处理节点失败等
- ETCD:一个可靠的分布式数据存储,能持久化存储集群配置
- 工作节点:它们运行用户实际部署的应用
- Docker、rtk或其他容器类型
- Kubelet:与API服务器通信,并管理它所在节点的容器
- Kubernetes Service Proxy:负责组建之间的负载均衡网络流量
Kubernetes运行应用
如上图所示,在应用描述符中列出了四个容器,并将这些容器分成了3组,这些集合被称为pod,其中前两个pod只包含了一个容器,最后一个包含两个,意味着这两个容器都需要协作运行,每个pod旁边的数字表示需要并行运行的每个pod的副本数量,在向 Kubernetes 提交描述符之后,它将 把每个 pod的指定副本数量调度到可用的工作节点上。 节点上的 Kubelets将告知 Docker 从镜像仓库中拉取 容器镜像井运 行容器 。
安装kubernetes
这里我使用的是Docker for Mac,具体安装方法可以参考下面链接
https://developer.aliyun.com/article/508460
安装完成之后验证Kubernetes是否安装成功
Kubernetes的优势
简化应用程序部署
更好的利用硬件
健康检查和自修复
- 自动扩容
Kubernetes组件说明
- APISERVER:所有服务访问统一接口
- ControllerManager:维护副本期望数据
- Scheduler:负责介绍任务,选择合适的节点进行分配任务
- ETCD:键值对数据库,存储K8S集群所有重要信息(持久化)
- Kubelet:直接跟容器引擎交互实现容器的生命周期管理
- Kube-proxy:负责写入规则至IPTABLES,IPVS实现服务映射访问
- COREDNS:可以为集群中的SVC创建一个域名IP的对应关系解析
- DASHBOARD:给K8S集群提供一个B/S结构访问体系
- INGRESS CONTROLLER:官方只能实现四层代理,INGRESS可以实现七层代理
- FEDERATION:提供一个可以跨集群中心多K8S统一管理功能
- PROMETHEUS:提供K8S集群的监控能力
- ELK:提供K8S集群日志统一分析接入平台
pod的介绍
一个pod是一组紧密相关的容器,它们总是一起运行在同一个工作节点上,以 及同一个 Linux 命名空间中。每个 pod就像一个独立的逻辑机器,拥有自己的 IP、 主机名、进程等,运行一个独立的应用程序 。应用程序可以是单个进程,运行在单个容器中,也可以是一个主应用进程或者其他支持进程,每个进程都在自己的容器中运行 。一 个pod的所有容器都运行在同一个逻辑机器上,而其他 pod 中的容器, 即使运行在同一个工作节点上,也会出现在不同的节点上 。
如下图所示是容器、pod以及物理工作节点之间的关系。从图上我们可以看出,每个pod都有自己的IP,并包含一个或多个容器,每个容器都运行一个应用进程,pod分布在不同的工作节点上。
部署一个Node.js应用,可以使用kubectl run
命令,该命令可以创建所有必要的组件而无需 ISON 或YAML文件,这样的话,我们就不需要深入了解每 个组件对象的结构。
1 | caoyifan@MacBookPro ~ % kubectl run kubia --image=luksa/kubia --port=8080 |
- —image=luksa/kubia显示的是指定要运行的容器镜像
- --port=8080选项告诉Kubernetes应用正在监昕 8080端口
列出pod
1 | caoyifan@MacBookPro ~ % kubectl get pods |
在Kubernetes中运行容器镜像所必需的步骤
- 构建镜像并将其推送到Docker Hub
- 当运行kubectl命令时,它通过向 Kubernetes API服务器发送一个REST HTTP请求,在集群中创建一个新的 ReplicationController对象 。 然后,ReplicationController创建了一个新的pod,调度器将其调度到一个工作节点上。Kubelet看到pod被调度到节点上,就告知 Docker 从镜像中心中拉取指定的镜像,因为本地没有该镜像。下载镜像后,Docker创建并运行容器。
创建一个服务对象
1 | caoyifan@MacBookPro ~ % kubectl expose pod kubia --type=LoadBalancer --name kubia-http |
列出服务
1 | caoyifan@MacBookPro ~ % kubectl get services |
这里我们会发现应用将pod名称作为它的主机名。因为每个pod都像一个独立的机器,具有自己的IP地址和主机名,尽管应用程序运行在工作节点的操作系统中,但对应用程序来说,它似乎是在一个独立的机器上运行,而这台机器本身就是应用程序的专用机器,没有其他的进程一同运行。
访问本地8080
端口向pod发送请求
1 | caoyifan@MacBookPro ~ % curl localhost:8080 |
Pod概念
自主式Pod
控制器管理的Pod
ReplicationController:用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的Pod来替代,而如果异常多出来的容器也会自动回收。
ReplicaSet:和ReplicationController没有本质不同,支持集合式的selector
Deployment:自动管理ReplicaSet,支持滚动更新
Horizontal Pod Autoscaling:仅适用于Deployment和ReplicaSet
StatefullSet:为了解决有状态服务的问题,应用场景包括:
- 稳定的持久化存储
- 稳定的网络标志
- 有序部署,有序扩展
- 有序收缩,有序删除
DaemonSet:确保全部(或者一些)Node上运行一个Pod的副本,当有Node加入集群时,也会为他们新增一个Pod,当有Node从集群中移除时,这些Pod也会被回收,删除DaemonSet将会删除它创建的所有Pod,使用DaemonSet的一些典型用法:
- 运行集群存储daemon,例如在每个Node上运行glusterd,ceph
- 在每个Node上运行日志收集daemon,例如fluentd,logstash
- 在每个Node上运行监控daemon,例如Prometheus,Node Exporter
Job:负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个Pod成功结束
Cron Job:管理基于时间的Job,即在给定时间点只运行一次,周期性地在给定时间点运行
以YAML或JSON描述文件创建pod
首先我们呢将使用-o yaml
选项的kubectl get
命令来获取pod的整个YAML定义
1 | kubectl get pod kubia -o yaml |
结果如下
1 | apiVersion: v1 #YAML描述文件所使用的Kubernetes API版本 |
为pod创建一个简单的YAML描述文件,名为kubia-manual.yaml
1 | apiVersion: v1 #描述文件遵循v1版本的Kubernetes API |
这里需要注意一下yaml
语法对格式是非常严格的,这里不可以有制表符,否则就会报如下相关错误
1 | error: error parsing kubia-manual.yaml: error converting YAML to JSON: yaml: line 4: found character that cannot start any token |
1 | error: error parsing kubia-manual.yaml: error converting YAML to JSON: yaml: line 8: found a tab character that violates indentation |
接下来使用kubectl create
从YAML文件创建pod
1 | kubectl create -f kubia-manual.yaml |
得到运行中pod的完整定义
1 | kubectl get pod kubia-manual -o yaml |
也可以返回JSON格式
1 | kubectl get pod kubia-manual -o json |
利用kubectl logs命令获取pod日志
1 | kubectl logs kubia-manual |
如果我们的pod包含多个容器,在运行kubectl logs命令时则必须通过包含-c <容器名称>
选项来显式指定容器名称。
1 | kubectl logs kubia-manual -c kubia |
向pod发送请求
将本地网络端口转发到pod中的端口
如果想要在不通过service的情况下与某个特定的pod 进行通信(出于调试或其他原因), Kubernetes将允许我们配置端口转发到该pod。 可以通过kubectl port-forward
命令完成上述操作。 例如以下命令会将机器的本地端口 8888转发 到我们的kubia-manual pod的端口8080
1 | caoyifan@MacBookPro ~ % kubectl port-forward kubia-manual 8888:8080 |
这个时候端口转发就在运行中,我们可以通过curl命令向pod发送一个HTTP请求
1 | caoyifan@MacBookPro ~ % curl localhost:8888 |
下图描述了使用kubectl port-forward
和curl
时的简单视图
标签
标签是一种简单却功能强大的Kubernetes特性,不仅可以组织pod, 也可以组织所有其他的Kubernetes资源。详细来讲,标签是可以附加到资源的任意键值对,用以选择具有该确切标签的资源(这是通过标答选择器完成的 )。只要标签的key在资源内是唯一的,一个资源便可以拥有多个标签。通常在我们创建资源时就会将标签附加到资源上,但之后我们也可以再添加其他标签,或者修改现有标签的值,而无需重新创建资源。
例如在微服务中,通过给pod添加标签,可以得到一个更组织化的系统。此时每个pod都标有两个标签
- app:指定pod属于哪个应用、组件或微服务
- rel:显示在pod中运行的应用程序版本是stable、beta还是canary
如下图所示,显示了使用pod标签组织微服务架构中的pod
创建pod时指定标签
首先创建一个名为kubia-manual-with-labels.yaml
的文件
代码如下,其中两个标签被附加到pod上
1 | apiVersion: v1 |
接下来创建该pod
1 | kubectl create -f kubia-manual-with-labels.yaml |
使用--show-labels
查看标签
1 | kubectl get pods --show-labels |
如果你只对某些标签感兴趣, 可以使用 -L 选项指定它们并将它们分别显示在 自己的列中, 而不是列出所有标签。 接下来我们再次列出所有 pod, 并将附加到 pod名为kubia-manual-v2
上的两个标签的列展示如下
1 | kubectl get pods -L creation_method,env |
修改现有pod的标签
标签也可以在现有 pod 上进行添加和修改。由于pod名为kubia-manual
也是手动创建的 所以我们可以为其添加 creation_method=manual
标签
1 | kubectl label pod kubia-manual creation_method=manual |
更改现有标签的值
1 | kubectl label pod kubia-manual-v2 env=debug --overwrite |
再次列出pod以查看更新后的标签
使用标签选择器列出pod
列出标签creation_method
的值为manual的pod
1 | kubectl get pod -l creation_method=manual |
列出包含env标签的所有pod 无论其值如何
1 | kubectl get pod -l env |
列出没有env标签的pod
注意这里要使用单引号来包含!env
1 | kubectl get pod -l '!env' |
发现其他命名空间及其pod
列出集群中所有的命名空间
1 | kubectl get ns |
这里需要声明的是,到目前为止,我们只在default
命名空间中进行操作,当使用kubecel get
命令列出资源时,我们从未明确指定命名空间,因此kubectl总是默认为default命名空间
列出指定命名空间的pod
1 | kubectl get pod --namespace kube-system |
创建一个命名空间
我们还是使用YAML文件来创建一个命名空间
创建一个名为custom-namespace.yaml
的文件
1 | apiVersion: v1 |
使用create命令创建
1 | kubectl create -f custom-namespace.yaml |
如果想要在刚创建的命名 空 间中创建资源,可以选择在metadata
字段中添加 一个 namespace : custom-namespace
属性,也可以在使用kubectl create
命令创建资源时指定命名空间 :
1 | kubectl create -f kubia-manual.yaml -n custom-namespace |
这个时候我们就得到了两个同名的pod(kubia-manual),其中一个在default
命名空间中,一个在custom-namespace
中
删除pod
按照名称删除pod
1 | kubectl delete pod kubia-manual |
使用标签选择器删除pod
1 | kubectl delete pod -l creation_method=manual |
通过删除整个命名空间来删除pod
1 | kubectl delete ns custom-namespace |