Как обновить только контейнер? - PullRequest
0 голосов
/ 15 мая 2018

Я работаю локально с Minikube, и каждый раз, когда я изменяю код, я удаляю сервис (и развертывание) и создаю новый.

Эта операция генерирует новый IP для каждого контейнерапоэтому мне также необходимо обновить мой веб-интерфейс, а также вставить новые данные в мой контейнер БД, поскольку я теряю все данные каждый раз, когда удаляю службу.

Это слишком много потерянного времени для эффективной работы.

Я хотел бы знать, есть ли способ обновить контейнер без создания новых IP-адресов и без удаления модуля (потому что я не хочу удалять свой контейнер БД каждый раз, когда обновляю код бэкэнда)?

Ответы [ 4 ]

0 голосов
/ 16 мая 2018

Я думаю, вам действительно нужно решить 2 вопроса:

  1. Не перезапускать сервис. Перезагрузите только свой модуль. Тогда служба не изменит свой IP-адрес.
  2. База данных и ваше приложение не обязательно должны быть двумя контейнерами в одном модуле. Они должны быть 2 отдельными стручками. Затем вам понадобится другой сервис для предоставления базы данных вашему приложению.

Итак, окончательное решение должно быть таким:

  1. модуль базы данных - запускается один раз, никогда не перезапускается во время разработки.
  2. служба базы данных - создается один раз, никогда не перезапускается.
  3. модуль приложения - это единственное, что вы перезагрузите при изменении кода приложения. Ему нужен доступ к базе данных, поэтому вы пишете буквально «database-service: 3306» или что-то подобное в вашем приложении. «database-service» - это название службы, которую вы создали в (2).
  4. служба приложений - создается один раз, никогда не перезапускается. Вы получаете доступ к приложению извне minikube, используя IP-адрес этой услуги.
0 голосов
/ 15 мая 2018

Используйте kops и создайте производственный кластер в AWS на бесплатном уровне. Чтобы это исправить, вы должны убедиться, что вы используете loadbalancer для своих интерфейсов. Создайте сервис для вашего контейнера базы данных, выставляя порт таким образом, чтобы ваши внешние интерфейсы могли к нему добраться, и вставьте его в свой манифест для своих внешних интерфейсов, чтобы он был статичным. Служба обнаружения позаботится о IP-адресе, и ваши контейнеры автоматически подключатся к портам. Вы также можете настроить постоянное хранилище для ваших БД. Когда вы обновите свой код внешнего интерфейса, используйте его для обновления ваших контейнеров, чтобы ничего не изменилось.

развертывание образа kubectl / развертывание helloworld basicnodeapp = buildmystartup / basicnodeapp: 2

Вот как я мог бы создать приложение с полным состоянием в производственном AWS на примере WordPress.

###############################################################################
#
# Creating a stateful app with persistent storage and front end containers
#
###############################################################################

* Here is how you create a stateful app using volumes and persistent storage for production.

* To start off we can automate the storage volume creation for our mysql server with a storage object and persistent volume claim like so:

$ cat storage.yml
kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
  name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
  zone: us-east-1b

  $ cat pv-claim.yml
  kind: PersistentVolumeClaim
  apiVersion: v1
  metadata:
    name: db-storage
    annotations:
      volume.beta.kubernetes.io/storage-class: "standard"
  spec:
    accessModes:
      - ReadWriteOnce
    resources:
      requests:
        storage: 8Gi

* Lets go ahead and create these so they are ready for our deployment of mysql

$ kubectl create -f storage.yml
storageclass "standard" created


$ kubectl create -f pv-claim.yml
persistentvolumeclaim "db-storage" created

* Lets also create our secrets file that will be needed for mysql and wordpress

$ cat wordpress-secrets.yml
apiVersion: v1
kind: Secret
metadata:
  name: wordpress-secrets
type: Opaque
data:
  db-password: cGFzc3dvcmQ=
  # random sha1 strings - change all these lines
  authkey: MTQ3ZDVhMTIzYmU1ZTRiMWQ1NzUyOWFlNWE2YzRjY2FhMDkyZGQ4OA==
  loggedinkey: MTQ3ZDVhMTIzYmU1ZTRiMWQ1NzUyOWFlNWE2YzRjY2FhMDkyZGQ4OQ==
  secureauthkey: MTQ3ZDVhMTIzYmU1ZTRiMWQ1NzUyOWFlNWE2YzRjY2FhMDkyZGQ5MQ==
  noncekey: MTQ3ZDVhMTIzYmU1ZTRiMWQ1NzUyOWFlNWE2YzRjY2FhMDkyZGQ5MA==
  authsalt: MTQ3ZDVhMTIzYmU1ZTRiMWQ1NzUyOWFlNWE2YzRjY2FhMDkyZGQ5Mg==
  secureauthsalt: MTQ3ZDVhMTIzYmU1ZTRiMWQ1NzUyOWFlNWE2YzRjY2FhMDkyZGQ5Mw==
  loggedinsalt: MTQ3ZDVhMTIzYmU1ZTRiMWQ1NzUyOWFlNWE2YzRjY2FhMDkyZGQ5NA==
  noncesalt: MTQ3ZDVhMTIzYmU1ZTRiMWQ1NzUyOWFlNWE2YzRjY2FhMDkyZGQ5NQ==

$ kubectl create -f wordpress-secrets.yml



* Take note of the names we assigned. We will need these for the mysql deployment

* We created the storage in us-east-1b so lets set a node label for our node in that AZ so our deployment is pushed to that node and can attach our volume.

$ kubectl label nodes ip-172-20-48-74.ec2.internal storage=mysql
node "ip-172-20-48-74.ec2.internal" labeled

* Here is our mysql pod definition. Notice at the bottom we use a nodeSelector
* We will need to use that same one for our deployment so it can reach us-east-1b


$ cat wordpress-db.yml
apiVersion: v1
kind: ReplicationController
metadata:
  name: wordpress-db
spec:
  replicas: 1
  selector:
    app: wordpress-db
  template:
    metadata:
      name: wordpress-db
      labels:
        app: wordpress-db
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        args:
          - "--ignore-db-dir=lost+found"
        ports:
        - name: mysql-port
          containerPort: 3306
        env:
          - name: MYSQL_ROOT_PASSWORD
            valueFrom:
              secretKeyRef:
                name: wordpress-secrets
                key: db-password
        volumeMounts:
        - mountPath: "/var/lib/mysql"
          name: mysql-storage
      volumes:
        - name: mysql-storage
          persistentVolumeClaim:
            claimName: db-storage
      nodeSelector:
        storage: mysql

* Before we go on to the deployment lets expose a service on port 3306 so wordpress can connect.

$ cat wordpress-db-service.yml
apiVersion: v1
kind: Service
metadata:
  name: wordpress-db
spec:
  ports:
  - port: 3306
    protocol: TCP
  selector:
    app: wordpress-db
  type: NodePort



$ kubectl create -f wordpress-db-service.yml
service "wordpress-db" created

* Now lets work on the deployment. We are going to use EFS to save all our pictures and blog posts so lets create that on us-east-1b also

* So first lets create our EFS NFS share

$ aws efs create-file-system --creation-token 1
{
    "NumberOfMountTargets": 0,
    "SizeInBytes": {
        "Value": 0
    },
    "CreationTime": 1501863105.0,
    "OwnerId": "812532545097",
    "FileSystemId": "fs-55ed701c",
    "LifeCycleState": "creating",
    "CreationToken": "1",
    "PerformanceMode": "generalPurpose"
}

$ aws efs create-mount-target --file-system-id fs-55ed701c --subnet-id subnet-7405f010 --security-groups sg-ffafb98e
{
    "OwnerId": "812532545097",
    "MountTargetId": "fsmt-a2f492eb",
    "IpAddress": "172.20.53.4",
    "LifeCycleState": "creating",
    "NetworkInterfaceId": "eni-cac952dd",
    "FileSystemId": "fs-55ed701c",
    "SubnetId": "subnet-7405f010"
}


* Before we launch the deployment lets make sure our mysql server is up and connected to the volume we created

$ kubectl get pvc
NAME         STATUS    VOLUME                                     CAPACITY   ACCESSMODES   STORAGECLASS   AGE
db-storage   Bound     pvc-82c889c3-7929-11e7-8ae1-02fa50f1a61c   8Gi        RWO           standard       51m

* ok status bound means our container is connected to the volume.

* Now lets launch the wordpress frontend of two replicas.

$ cat wordpress-web.yml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: wordpress-deployment
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
      - name: wordpress
        image: wordpress:4-php7.0
        # uncomment to fix perm issue, see also https://github.com/kubernetes/kubernetes/issues/2630
        # command: ['bash', '-c', 'chown', 'www-data:www-data', '/var/www/html/wp-content/upload', '&&', 'apache2', '-DFOREGROUND']
        ports:
        - name: http-port
          containerPort: 80
        env:
          - name: WORDPRESS_DB_PASSWORD
            valueFrom:
              secretKeyRef:
                name: wordpress-secrets
                key: db-password
          - name: WORDPRESS_AUTH_KEY
            valueFrom:
              secretKeyRef:
                name: wordpress-secrets
                key: authkey
          - name: WORDPRESS_LOGGED_IN_KEY
            valueFrom:
              secretKeyRef:
                name: wordpress-secrets
                key: loggedinkey
          - name: WORDPRESS_SECURE_AUTH_KEY
            valueFrom:
              secretKeyRef:
                name: wordpress-secrets
                key: secureauthkey
          - name: WORDPRESS_NONCE_KEY
            valueFrom:
              secretKeyRef:
                name: wordpress-secrets
                key: noncekey
          - name: WORDPRESS_AUTH_SALT
            valueFrom:
              secretKeyRef:
                name: wordpress-secrets
                key: authsalt
          - name: WORDPRESS_SECURE_AUTH_SALT
            valueFrom:
              secretKeyRef:
                name: wordpress-secrets
                key: secureauthsalt
          - name: WORDPRESS_LOGGED_IN_SALT
            valueFrom:
              secretKeyRef:
                name: wordpress-secrets
                key: loggedinsalt
          - name: WORDPRESS_NONCE_SALT
            valueFrom:
              secretKeyRef:
                name: wordpress-secrets
                key: noncesalt
          - name: WORDPRESS_DB_HOST
            value: wordpress-db
        volumeMounts:
        - mountPath: /var/www/html/wp-content/uploads
          name: uploads
      volumes:
      - name: uploads
        nfs:
          server: us-east-1b.fs-55ed701c.efs.us-east-1.amazonaws.com
          path: /

* Notice we put together a string for the NFS share.
* AZ.fs-id.Region.amazonaws.com

* Now lets create our deployment.

$ kubectl create -f wordpress-web.yml

$ cat wordpress-web-service.yml
apiVersion: v1
kind: Service
metadata:
  name: wordpress
spec:
  ports:
  - port: 80
    targetPort: http-port
    protocol: TCP
  selector:
    app: wordpress
  type: LoadBalancer


* And now the load balancer for our two nodes

$ kubectl create -f wordpress-web-service.yml


* Now lets find our ELB and create a Route53 DNS name for it.

$ kubectl get services

$ kubectl describe service wordpress
Name:           wordpress
Namespace:      default
Labels:         <none>
Annotations:        <none>
Selector:       app=wordpress
Type:           LoadBalancer
IP:         100.70.74.90
LoadBalancer Ingress:   acf99336a792b11e78ae102fa50f1a61-516654231.us-east-1.elb.amazonaws.com
Port:           <unset> 80/TCP
NodePort:       <unset> 30601/TCP
Endpoints:      100.124.209.16:80,100.94.7.215:80
Session Affinity:   None
Events:
  FirstSeen LastSeen    Count   From            SubObjectPath   Type        Reason          Message
  --------- --------    -----   ----            -------------   --------    ------          -------
  38m       38m     1   service-controller          Normal      CreatingLoadBalancer    Creating load balancer
  38m       38m     1   service-controller          Normal      CreatedLoadBalancer Created load balancer

  $ kubectl get deployments
  NAME                   DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
  wordpress-deployment   2         2         2            2           2m


  $ kubectl get pods
  NAME                                    READY     STATUS              RESTARTS   AGE
  sysdig-agent-4sxv2                      1/1       Running             0          3d
  sysdig-agent-nb2wk                      1/1       Running             0          3d
  sysdig-agent-z42zj                      1/1       Running             0          3d
  wordpress-db-79z87                      1/1       Running             0          54m
  wordpress-deployment-2971992143-c8gg4   0/1       ContainerCreating   0          1m
  wordpress-deployment-2971992143-h36v1   1/1       Running             0          1m
0 голосов
/ 15 мая 2018

Легко обновить существующее Развертывание новым образом без необходимости его удаления.

Представьте, что у нас есть файл YAML с Развертыванием.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

Чтобы запустить это развертывание, выполните следующую команду:

$ kubectl create -f nginx-deployment.yaml --record

(--record - добавляет текущую команду к аннотациям созданного или обновленного ресурса. Это полезно для будущегопроверяет, например, выясняет, какие команды выполнялись в каждой ревизии развертывания, и выполняет откат.)

Чтобы увидеть состояние развертывания развертывания, выполните

$ kubectl rollout status deployment/nginx-deployment

Чтобы обновить версию образа nginx,просто запустите команду:

$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1

Или вы можете отредактировать существующее развертывание с помощью команды:

$ kubectl edit deployment/nginx-deployment

Чтобы просмотреть состояние процесса обновления развертывания, введите команду:

$ kubectl rollout status deployment/nginx-deployment
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
deployment "nginx-deployment" successfully rolled out

или

$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           36s

Каждый раз, когда вы обновляете Deployment, он обновляет модули, создавая новый ReplicaSet, масштабируя его до 3-х реплик и уменьшая старый ReplicaSet до 0. Если вы обновляетеПри повторном развертывании во время предыдущего обновления он начинает создавать новый ReplicaSet немедленно, не дожидаясь завершения предыдущего обновления.

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-1180356465   3         3         3       4s
nginx-deployment-2538420311   0         0         0       56s

Если вы сделали опечатку во время редактирования развертывания (например,nginx: 1.91) вы можете откатить его до предыдущей хорошей версии.
Сначала проверьте версии этого развертывания:

$ kubectl rollout history deployment/nginx-deployment
deployments "nginx-deployment"
REVISION    CHANGE-CAUSE
1           kubectl create -f nginx-deployment.yaml --record
2           kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
3           kubectl set image deployment/nginx-deployment nginx=nginx:1.91

Поскольку мы записали команду при создании этого развертывания с помощью --record, мыможно легко увидеть изменения, которые мы внесли в каждую ревизию.

Чтобы просмотреть подробную информацию о каждой ревизии, выполните:

$ kubectl rollout history deployment/nginx-deployment --revision=2
deployments "nginx-deployment" revision 2
  Labels:       app=nginx
          pod-template-hash=1159050644
  Annotations:  kubernetes.io/change-cause=kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
  Containers:
   nginx:
    Image:      nginx:1.9.1
    Port:       80/TCP
     QoS Tier:
        cpu:      BestEffort
        memory:   BestEffort
    Environment Variables:      <none>
  No volumes.

Теперь вы можете выполнить откат к предыдущей версии, используя команду:

$ kubectl rollout undo deployment/nginx-deployment
deployment "nginx-deployment" rolled back

Или вы можете выполнить откат к определенной версии:

$ kubectl rollout undo deployment/nginx-deployment --to-revision=2
deployment "nginx-deployment" rolled back

Для получения дополнительной информации, пожалуйста, прочитайте часть документации Kubernetes, относящуюся к Развертывание

0 голосов
/ 15 мая 2018

Прежде всего, во внешнем интерфейсе используйте DNS-имена вместо IP-адресов для доступа к своему бэкэнду.Это избавит вас от необходимости перестраивать ваше интерфейсное приложение при каждом развертывании бэкэнда.

При этом нет необходимости удалять ваш сервис только для развертывания новой версии бэкэнда.На самом деле, вам просто нужно обновить свое развертывание, чтобы оно ссылалось на созданный вами новый образ докера с использованием самого последнего кода для вашего бэкэнда.

Наконец, насколько я понимаю, ваше приложение и база данных находятся в одном модуле.Это не очень хорошая практика, вы должны разделять их, чтобы не вызывать простои в вашей базе данных при развертывании новой версии вашего кода.

Как примечание, не уверен, что это так, ноЕсли вы используете Minikube в качестве среды разработки, вы, вероятно, делаете это неправильно.Вы должны использовать только докер с привязкой тома, но это выходит за рамки вашего вопроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...