生产环境中使用Kubernetes - Working with Containers in Production

标签: | 发表时间:2022-01-15 16:30 | 作者:
出处:https://jamesdefabia.github.io

持久存储

容器文件系统的生命周期与容器的生命周期一样长,因此当容器崩溃并重新启动时,对文件系统的更改将丢失,容器将从全新的状态重新启动。要在容器文件系统之外访问更持久的存储,您需要一个 。这对于有状态的应用程序尤其重要,例如键值存储和数据库。

例如, Redis是一个键值缓存和存储,我们在 留言簿和其他示例中使用它。我们可以向它添加一个卷来存储持久数据,如下所示:

redis-deployment.yaml
      apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: redis
spec:
  template:
    metadata:
      labels:
        app: redis
        tier: backend
    spec:
      # Provision a fresh volume for the pod
      volumes:
        - name: data
          emptyDir: {}
      containers:
      - name: redis
        image: kubernetes/redis:v1
        ports:
        - containerPort: 6379
        # Mount the volume into the pod
        volumeMounts:
        - mountPath: /redis-master-data
          name: data   # must match the name of the volume, above

emptyDir卷的生命周期是 pod的生命周期,它比任何一个容器的生命周期都要长,所以如果容器失败并重新启动,我们的存储将继续存在。

除了 Kubernetes 提供的本地磁盘存储外 emptyDir,Kubernetes 还支持许多不同的网络附加存储解决方案,包括 GCE 上的 PD 和 EC2 上的 EBS,它们是关键数据的首选,并会处理节点上的设备挂载和卸载等细节. 有关更多详细信息,请参 阅卷文档

分发凭据

许多应用程序需要凭据(例如密码、OAuth 令牌和 TLS 密钥)来与其他应用程序、数据库和服务进行身份验证。将这些凭据存储在容器映像或环境变量中并不理想,因为任何有权访问映像、pod/容器规范、主机文件系统或主机 Docker 守护程序的人都可以复制这些凭据。

Kubernetes 提供了一种称为 secrets的机制,可以方便地将敏感凭证传递给应用程序。A Secret是一个包含数据映射的简单资源。例如,您可以使用用户名和密码创建一个简单的秘密,如下所示:

   $ kubectl create secret generic mysecret --from-literal=username="admin",password="1234"
secret "mysecret" created

这相当于 kubectl create -f

   apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: MTIzNA==

与其他资源一样,创建的秘密可以通过以下方式查看 get

   $ kubectl get secrets
NAME                  TYPE                                  DATA      AGE
default-token-zirbw   kubernetes.io/service-account-token   3         3h
mysecret              Opaque                                2         2m

要使用密钥,您需要在 pod 或 pod 模板中引用它。卷 secret源使您可以将其作为内存目录挂载到容器中。

redis-secret-deployment.yaml
      apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: redis
spec:
  template:
    metadata:
      labels:
        app: redis
        tier: backend
    spec:
      volumes:
        - name: data
          emptyDir: {}
        - name: supersecret # The "mysecret" secret populates this "supersecret" volume. 
          secret:
            secretName: mysecret
      containers:
      - name: redis
        image: kubernetes/redis:v1
        ports:
        - containerPort: 6379
        volumeMounts:
        - mountPath: /redis-master-data
          name: data
        - mountPath: /var/run/secrets/super # Mount the "supersecret" volume into the pod.
          name: supersecret

有关更多详细信息,请参阅 机密文档示例设计文档

使用私有镜像注册中心进行身份验证

秘密也可用于传递 图像注册表凭据

为 Docker 注册表创建 secret 的最简单方法是:

   $ kubectl create secret docker-registry myregistrykey --docker-username=janedoe --docker-password=●●●●●●●●●●● [email protected]
secret "myregistrykey" created

或者,您可以通过以下步骤执行等效操作。首先,创建一个 .docker/config.json,例如通过运行 docker login <registry.domain>。然后将生成的 .docker/config.json文件放入一个 秘密资源中。例如:

   $ docker login
Username: janedoe
Password: ●●●●●●●●●●●
Email: [email protected]
WARNING: login credentials saved in /Users/jdoe/.docker/config.json.
Login Succeeded

$ echo $(cat ~/.docker/config.json)
{ "https://index.docker.io/v1/": { "auth": "ZmFrZXBhc3N3b3JkMTIK", "email": "[email protected]" } }

$ cat ~/.docker/config.json | base64
eyAiaHR0cHM6Ly9pbmRleC5kb2NrZXIuaW8vdjEvIjogeyAiYXV0aCI6ICJabUZyWlhCaGMzTjNiM0prTVRJSyIsICJlbWFpbCI6ICJqZG9lQGV4YW1wbGUuY29tIiB9IH0K

$ cat > /tmp/image-pull-secret.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: myregistrykey
data:
  .dockerconfigjson: eyAiaHR0cHM6Ly9pbmRleC5kb2NrZXIuaW8vdjEvIjogeyAiYXV0aCI6ICJabUZyWlhCaGMzTjNiM0prTVRJSyIsICJlbWFpbCI6ICJqZG9lQGV4YW1wbGUuY29tIiB9IH0K
type: kubernetes.io/dockerconfigjson
EOF

$ kubectl create -f /tmp/image-pull-secret.yaml
secret "myregistrykey" created

imagePullSecrets 现在,您可以通过在 pod 定义中添加一个部分来创建引用该机密的 pod。

   apiVersion: v1
kind: Pod
metadata:
  name: foo
spec:
  containers:
    - name: foo
      image: janedoe/awesomeapp:v1
  imagePullSecrets:
    - name: myregistrykey

辅助容器

Pod支持同时运行多个容器。它们可用于托管垂直集成的应用程序堆栈,但它们的主要动机是支持辅助主要应用程序的辅助帮助程序。典型的例子是数据拉取器、数据推送器和代理。

这样的容器通常需要相互通信,通常是通过文件系统。这可以通过将相同的卷安装到两个容器中来实现。这种模式的一个例子是一个 Web 服务器,它带有一个 轮询 git 存储库以获取新更新的程序:

   apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-nginx
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      volumes:
      - name: www-data
        emptyDir: {}
      containers:
      - name: nginx
        image: nginx
        # This container reads from the www-data volume
        volumeMounts:
        - mountPath: /srv/www
          name: www-data
          readOnly: true
      - name: git-monitor
        image: myrepo/git-monitor
        env:
        - name: GIT_REPO
          value: http://github.com/some/repo.git
        # This container writes to the www-data volume
        volumeMounts:
        - mountPath: /data
          name: www-data

更多示例可以在我们的 博客文章演示幻灯片中找到。

资源管理

Kubernetes 的调度器只会将应用程序放置在它们有足够 CPU 和内存的地方,但它只有在知道它们需要多少 资源的情况下才能这样做。指定太少 CPU 的后果是,如果太多其他容器被调度到同一节点上,容器可能会缺乏 CPU。同样,如果没有请求内存,容器可能会因内存不足而意外死亡,这对于大内存应用程序尤其可能。

如果没有指定资源需求,则假定资源的名义数量。(此默认值通过默认 Namespace的 LimitRange应用。可以使用 查看。)您可以明确指定所需的资源量,如下所示: kubectl describe limitrange limits

redis-resource-deployment.yaml
      apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: redis
spec:
  template:
    metadata:
      labels:
        app: redis
        tier: backend
    spec:
      containers:
      - name: redis
        image: kubernetes/redis:v1
        ports:
        - containerPort: 80
        resources:
          limits:
            # cpu units are cores
            cpu: 500m
            # memory units are bytes
            memory: 64Mi
          requests:
            # cpu units are cores
            cpu: 500m
            # memory units are bytes
            memory: 64Mi

如果容器超过其指定的限制,容器将因 OOM(内存不足)而死亡,因此指定一个略高于预期的值通常会提高可靠性。通过指定请求,可以保证 pod 在需要时能够使用那么多资源。有关资源限制和请求之间的区别,请参阅 资源 QoS 。

如果您不确定要请求多少资源,您可以先启动应用程序而不指定资源,然后使用 资源使用监控来确定适当的值。

Liveness 和 Readiness 探测(又名健康检查)

许多长时间运行的应用程序最终会转变为损坏状态,除非重新启动它们,否则无法恢复。Kubernetes 提供了 活性探针来检测和补救这种情况。

探测应用程序的常用方法是使用 HTTP,可以按如下方式指定:

nginx-probe-deployment.yaml
      apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        livenessProbe:
          httpGet:
            # Path to probe; should be cheap, but representative of typical behavior
            path: /index.html
            port: 80
          initialDelaySeconds: 30
          timeoutSeconds: 1

其他时候,应用只是暂时无法服务,会自行恢复。通常在这种情况下,您不希望终止应用程序,但也不想向其发送请求,因为应用程序将无法正确响应或根本无法响应。常见的此类场景是在应用程序启动期间加载大型数据或配置文件。Kubernetes 提供 就绪探针来检测和缓解此类情况。Readiness 探针的配置与 liveness 探针类似,只是使用该 readinessProbe字段。带有容器报告它们尚未准备好的 pod 将不会通过 Kubernetes 服务接收流量。

有关更多详细信息(例如,如何指定基于命令的探测),请参阅 演练中的示例、 独立示例文档

生命周期钩子和终止通知

当然,节点和应用程序可能随时发生故障,但许多应用程序受益于干净关闭,例如在有意终止应用程序时完成正在进行的请求。为了支持这种情况,Kubernetes 支持两种通知:

  • Kubernetes 将向应用程序发送 SIGTERM,可以对其进行处理以实现优雅终止。如果应用程序没有提前终止(默认为 30 秒,由 控制 spec.terminationGracePeriodSeconds),则会在可配置的秒数后发送 SIGKILL。
  • Kubernetes 支持 pre-stop 生命周期钩子的(可选)规范,它将在发送 SIGTERM 之前执行。

pre-stop hook 的规格与probe 的规格类似,但没有与时间相关的参数。例如:

nginx-lifecycle-deployment.yaml
      apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        lifecycle:
          preStop:
            exec:
              # SIGTERM triggers a quick exit; gracefully terminate instead
              command: ["/usr/sbin/nginx","-s","quit"]

终止消息

为了达到相当高的可用性水平,特别是对于积极开发的应用程序,快速调试故障非常重要。除了常规 日志收集之外, Kubernetes 还可以通过使用UI kubectlUI显示致命错误的原因来加速调试。可以指定容器将在何处写入其“死亡声音”,例如断言失败消息、堆栈跟踪、异常等。默认路径是. terminationMessagePath /dev/termination-log

这是一个玩具示例:

pod-w-message.yaml
      apiVersion: v1
kind: Pod
metadata:
  name: pod-w-message
spec:
  containers:
  - name: messager
    image: "ubuntu:14.04"
    command: ["/bin/sh","-c"]
    args: ["sleep 60 && /bin/echo Sleep expired > /dev/termination-log"]

该消息与最后(即最近)终止的其他状态一起记录:

   $ kubectl create -f ./pod-w-message.yaml
pod "pod-w-message" created
$ sleep 70
$ kubectl get pods/pod-w-message -o go-template="{{range .status.containerStatuses}}{{.lastState.terminated.message}}{{end}}"
Sleep expired
$ kubectl get pods/pod-w-message -o go-template="{{range .status.containerStatuses}}{{.lastState.terminated.exitCode}}{{end}}"
0

相关 [生产 环境 中使] 推荐:

生产环境中使用Kubernetes - Working with Containers in Production

- -
容器文件系统的生命周期与容器的生命周期一样长,因此当容器崩溃并重新启动时,对文件系统的更改将丢失,容器将从全新的状态重新启动. 要在容器文件系统之外访问更持久的存储,您需要一个. 这对于有状态的应用程序尤其重要,例如键值存储和数据库. 例如, Redis是一个键值缓存和存储,我们在 留言簿和其他示例中使用它.

在生产环境运行容器

- - IT瘾-tuicool
【编者的话】Vivek Juneja是一名工作首尔的云服务工程师. 他从2008年就开始接触云服务,是最早的AWS和Eucalyptus的使用者. 本文中总结了在生产环境中使用容器的几个方面,特别是对虚拟机与容器的混合部署的观点很值得推荐给大家. 如果只是把容器限制在开发测试环境中,那么您并没有享受到面向容器研发和发布工作的全部红利.

MySQL生产环境突发故障处理手册

- gOODiDEA - MySQL OPS
1.2 碎片整理和统计信息更新 OPTIMIZE 操作等于recreate + analyze 的组合操作,所以会堵塞更新类型SQL语句. 对于备机上跑只读类型操作的业务,可以考虑使用此操作命令,对于主服务器不建议使用此命令,为此备机上执行OPTIMIZE 语句,必须这样写: [...].

生产环境 MySQL 表的维护:check、optimize和analyze

- - CSDN博客数据库推荐文章
        optimize可以回收空间、减少碎片、提高I/O.         目前支持的存储引擎有:InnoDB、MyASIM和ARCHIVE.         如果是Replication环境、可加NO_WRITE_TO_BINLOG(或者LOCAL、意思完全相同)、比如:.         以下是一个简单测试:.

[MySQL] 生产环境MySQL数据库事务一直在RUNNING

- - CSDN博客数据库推荐文章
运营人员反映,有一单子提交卡住了,页面一直没有返回. 1,刚开始怀疑是应用服务器或者db压力过高hang住了,马上去check应用服务器以及db的负载,看起来都OK,蛮低的,应该不是DB性能问题. 2,最后去看下是否是表锁住了,查看到有2个事务一直RUNNING,没有结束. 3,通过trx_mysql_thread_id: 1662332的去查询information_schema.processlist找到执行事务的客户端请求的SQL线程.

[原]BTrace介绍和生产环境例子

- - Vern的专栏
BTrace 是一个可靠的,用来动态跟踪Java程序的工具. 它通过动态对运行中的Java程序进行字节码生成来工作. BTrace会对运行中的Java程序的类插入一些跟踪操作 来对被跟踪的程序进行热替换. 探测点 (Probe Point). 就是一系列的跟踪语句被执行的“地方”或者“事件”. 探测点就是我们想要执行一些跟踪语句的地方或者事件.

virgo-tomcat-server的生产环境线上配置与管理 - 520_1351

- - 博客园_首页
Virgo Tomcat Server简称VTS,VTS是一个应用服务器,它是轻量级, 模块化, 基于OSGi系统. 与OSGi紧密结合并且可以开发bundles形式的Spring web apps应用. 他们同样拥有OSGi和Spring的特性. VTS由SpringSource 的Spring DM server过渡而来, virgo官网地址: http://www.eclipse.org/virgo.

生产环境下JAVA进程高CPU占用故障排查

- - 开源软件 - ITeye博客
生产环境下的某台tomcat7服务器,在刚发布时的时候一切都很正常,在运行一段时间后就出现CPU占用很高的问题,基本上是负载一天比一天高. 1,程序属于CPU密集型,和开发沟通过,排除此类情况. 2,程序代码有问题,出现死循环,可能性极大. 1,开发那边无法排查代码某个模块有问题,从日志上也无法分析得出.

生产环境用Docker?先搞定这8个常见故障

- - DockOne.io
维护生产环境中的Docker虚拟化应用,高效、稳定的运行至关重要. 但是,对于Docker的初学者而言,当容器或应用出现了问题,往往不知从何入手进行排查. Docker虚拟化主要有三类故障:. 应用故障:应用执行状态与预期不一致. 容器故障:无法正确创建、停止、更新容器等. 集群故障:集群创建失败、更新失败、无法连接等.

生产环境中的Kubernetes最佳实践

- - DockOne.io
2020年,12月1日 Pavan Belagatti. DevOps从提出到现在,已经走过了一段很长的路. 包括Docker和Kubernetes在内的多种平台也已经帮助企业用前所未有的速度实现了软件应用的交付. 同时,随着应用的容器化构建和发布比率不断上升,作为事实上的容器编排工具,Kubernetes在企业用户中备受欢迎和广泛认可.