环境搭建
docker
推荐使用Docker Desktop来安装,根据操作系统选择对应的安装包即可。
https://www.docker.com/products/docker-desktop/
安装完成后通过docker run hello-world
来验证是否安装成功:
安装成功。
minikube
还需要在本地搭建一套k8s集群,这里使用minikube
https://minikube.sigs.k8s.io/docs/start/?arch=%2Fmacos%2Farm64%2Fstable%2Fbinary+download
在mac中,直接用brew安装即可:
brew install minikube
如果是使用Docker Desktop的方式安装的docker,使用如下命令启动minikube即可:
minikube start --vm-driver docker --container-runtime=docker
通过minikube status
查看当前状态:
minikube常见命令如下:
•minikube stop: 不删除数据,停止VM和k8s集群•minikube delete:删除所有minikube启动后的数据•minikube ip:查看集群和docker enginer运行的ip地址•minikube pause:暂停当前资源和k8s集群•minikube status:查看当前集群状态
kubectl
安装完minikube之后,可以通过minikube kubectl
来执行相关命令,如果希望执行的命令更为简洁,可以直接安装kubectl,后续命令直接使用kubectl
即可。
mac中使用如下命令来安装:
brew install kubectl
docker hub
minikube默认镜像地址为DockerHub,因此需要在DockerHub(https://hub.docker.com/)中注册账号,并通过docker login命令来登录账号。
Container
如果有如下代码main.go:
package main
import(
"io"
"net/http"
)
func hello(w http.ResponseWriter, r *http.Request){
io.WriteString(w,"[v1] Hello, Kubernetes!")
}
func main(){
http.HandleFunc("/", hello)
http.ListenAndServe(":3000",nil)
}
这段代码启动了HTTP服务器,监听3000端口,如果访问/
路由,就会返回[v1] Hello, Kubernetes!
如果在真实的物理环境中运行,需要安装golang环境,熟悉go module的基本使用等等,但是如果依赖于容器技术,只需要一个
Dockerfile文件,加上想要运行的代码即可。
Dockerfile:
# Dockerfile
FROM golang:1.16-buster AS builder
RUN mkdir /src
ADD ./src
WORKDIR /src
RUN go env -w GO111MODULE=auto
RUN go build -o main .
FROM gcr.io/distroless/base-debian10
WORKDIR /
COPY --from=builder /src/main /main
EXPOSE 3000
ENTRYPOINT ["/main"]
这个Dockerfile使用多阶段进行构建。第一阶段从golang:1.16-buster基础镜像中构建应用程序,生成可执行文件main,第二阶段基于gcr.io/distroless/base-debian10构建基础镜像,将main可执行文件复制到镜像中,开放3000端口,并将/main作为容器入口点。
注意,需要将main.go和Dockerfile放到同一目录下,下面开始docker build:
docker build . -t rynnnn617/hellok8s:v1
其中rynnnn617是在dockerhub中注册的用户名,v1表示是第一个版本。
docker images:
下面启动容器:docker run -p 3000:3000 --name hellok8s -d rynnnn617/hellok8s:v1
-p来映射端口,-d后台运行
成功。
还可以通过docker push将镜像上传到docker hub仓库中:
docker push rynnnn617/hellok8s:v1
Pod
Pod是可以在kubernetes中创建,管理和部署的最小单元。
编写如下一个yaml,来创建一个nginx的pod:
# nginx.yaml
apiVersion: v1
kind:Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx-container
image: nginx
kind代表资源类型,metadata.name表示该pod的名字为nginx-pod(必须是唯一的),spec.containers下的字段表示容器和镜像名称。
通过kubectl apply -f nginx.yaml
命令来创建pod:
查看pod状态:
最后将端口映射出来:
kubectl port-forward nginx-pod 4000:80
也可以参考docker,通过如下命令进入pod:
kubectl exec -it nging-pod -- /bin/bsah
在shell里直接访问80端口或者映射出来后访问4000端口是一样的效果。
pod还有一些常用的命令:
kubectl logs --follow nginx-pod
kubectl exec nginx-pod -- ls
# pod "nginx-pod" deleted
kubectl delete pod nginx-pod
kubectl delete-f nginx.yaml
最后将前面通过Dockerfile和main.go构建的hellok8s:v1,用pod来实现:
apiVersion: v1
kind:Pod
metadata:
name: hellok8s
spec:
containers:
- name: hellok8s-container
image: rynnnn617/hellok8s:v1
kubectl apply -f hellok8s.yaml
kubectl get pods
kubectl port-forward hellok8s 3000:3000
pod&container
pod和container的区别如下:
•Pod 是 Kubernetes 的最小部署单位,它可以包含一个或多个容器。Pod中的容器共享网络和存储资源,它们运行在同一个命名空间下,并且可以通过本地的localhost进行通信。Pod可以共享数据,并且在同一个Pod中的容器通常用于运行协同工作的服务。•Container 是应用程序及其所有依赖的封装单位,它包含应用程序需要的所有文件、库和环境变量。在Kubernetes中,Pod中的一个或多个容器运行应用程序,并共享资源。容器是部署在Pod内的最小执行单元,通常用于封装单个应用程序或服务。
因此,可以说Pod是Kubernetes的调度单位,而容器是 Pod 中实际运行的应用程序的封装单位。Pod提供了一个逻辑上的封装,可以保证Pod内的容器共享资源,方便管理和部署应用程序。
Deployment
deployment是一种资源对象,用于对Pod进行管理控制。他提供了一种声明性的方式来定义和管理应用程序的部署,用户可依此管理应用程序的升级,扩容,回滚等操作。
扩容
首先创建一个yaml来管理hellok8s pod,deployment.yaml:
apiVersion: apps/v1
kind:Deployment
metadata:
name: hellok8s-deployment
spec:
replicas:1
selector:
matchLabels:
app: hellok8s
template:
metadata:
labels:
app: hellok8s
spec:
containers:
- image: rynnnn617/hellok8s:v1
name: hellok8s-container
kind表示为deployment类型,metadata.name同样代表deployment的名称,需要唯一,重点需要关注spec下的部分字段。
replicas表示部署的pod的数量,selector中表示deployment和pod资源关联的方式,此处代表deployment会管理所有labels为hellok8s的pod。
template部分用来定义pod资源,metadata.labels和上面的labels对应,并且deployment会自动为每个pod创建一个唯一的pod,所以不需要再定义metadata.name。
kubectl apply -f deployment.yaml
kubectl get pods
kubectl port-forward [pod-name]3000:3000
成功,并且可以看到deployment给了pod一个随机的名称:hellok8s-deployment-5f787f87f4-dg7rg
下面尝试删除该pod:
虽然删除了一个pod,但是deployment又自动创建了一个新pod,因为在deployment.yaml中定义了pod副本数量为1.
下面尝试对其进行扩容,将replicas改为3,表示pod副本数量为3:
apply之前,通过kubectl get pods --watch
观察pod创建情况,可以看到原有的一个pod没有变化,但是pending了两个新pod,随后变为containercreating状态,最后均进入running模式,共有3个pod。仅通过修改一个参数,实现了扩容。
升级
下面模拟升级版本。
修改main.go文件,将打印输出的v1改为v2,并重新制作镜像,上传:
kubectl apply -f deployment.yaml
,再kubectl get pods
查看:
开始会报错errimagepull,随后原先的3个pod会被删除,并创建3个新的pod,验证一下:
滚动更新
在真实的生产环境中,如果需要对pod进行升级,按照前面的方式会导致在短期内,服务是完全不可用的,需要等待第一个升级完的pod正常运行才行。因此有了这里提到的滚动更新,Rolling Update.
在deployment的定义中,spec.strategy.type有两类:
•Rolling Update:逐渐增加新版本pod•Recreate:先删除旧版本pod,再增加新版本pod
Rolloing Update就能解决前面提到的问题,而对于Rolling Update,又可以通过maxSurge和maxUnavailable来控制。
•maxSurge:制定可以创建的超出期望的pod数量•maxUnavailable:制定升级过程中不可用的pod个数上限
下面先回滚之前的操作,再进行滚动升级。
kubectl rollout undo deployment hellok8s-deployment
•undo: 撤销(回滚)更新操作•deployment: 要进行回滚操作的资源类型,这里指的是 Deployment 资源类型•hellok8s-deployment: Deployment 资源的名称,即deployment.yaml中的metadata.name,并非yaml文件的文件名
回滚之后再查看一下版本:
除了前面端口映射直接访问之外,还可以通过kubectl describe pod [pod-name]
来查看pod信息,可以看到已经回滚到v1版本。
除了undo,也可以通过history命令来查看历史版本,结合-- to-revision参数来回滚到指定版本:
kubectl rollout history deployment hellok8s-deployment
kubectl rollout undo deployment/hellok8s-deployment --to-revision=2
下面修改deployment.yaml来进行滚动升级:
apiVersion: apps/v1
kind:Deployment
metadata:
name: hellok8s-deployment
spec:
strategy:
rollingUpdate:
maxSurge:1
maxUnavailable:1
replicas:3
selector:
matchLabels:
app: hellok8s
template:
metadata:
labels:
app: hellok8s
spec:
containers:
- image: rynnnn617/hellok8s:v2
name: hellok8s-container
主要的变化在于:
spec:
strategy:
rollingUpdate:
maxSurge:1
maxUnavailable:1
表示在升级过程中,最多可能会创建4个pod(replicas+maxSurge),最少会有两个pod存活(replicas-maxUnavailable)。
看一下效果:
可以看到,-rwqd5这个pod,是在两个pod升级完成之后再terminating,这就保证了服务的可用性。
未完待续
参考链接:GitHub - guangzhengli/k8s-tutorials: k8s tutorials | k8s 教程
原文始发于微信公众号(Crush Sec):云原生01—K8s
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论