This is the multi-page printable view of this section. Click here to print.
Executar Aplicações
- 1: Executar uma Aplicação Sem Estado com um Deployment
- 2: Executar uma Aplicação Com Estado e de Instância Única
- 3: Acessando a API do Kubernetes a partir de um Pod
1 - Executar uma Aplicação Sem Estado com um Deployment
Esta página mostra como executar uma aplicação usando um objeto Deployment do Kubernetes.
Objetivos
- Criar uma instalação do nginx com um Deployment.
- Usar o kubectl para listar informações sobre o Deployment.
- Atualizar o Deployment.
Antes de você começar
Você precisa ter um cluster do Kubernetes e a ferramenta de linha de comando kubectl deve estar configurada para se comunicar com seu cluster. É recomendado executar esse tutorial em um cluster com pelo menos dois nós que não estejam atuando como hosts de camada de gerenciamento. Se você ainda não possui um cluster, pode criar um usando o minikube ou pode usar um dos seguintes ambientes:
O seu servidor Kubernetes deve estar numa versão igual ou superior a v1.9.Para verificar a versão, digite kubectl version
.
Criando e explorando uma instalação do nginx com um Deployment
Você pode executar uma aplicação criando um objeto Deployment do Kubernetes, e pode descrever um Deployment em um arquivo YAML. Por exemplo, este arquivo YAML descreve um Deployment que executa a imagem do contêiner nginx:1.14.2:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # diz ao deployment para executar 2 pods que correspondam ao modelo
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
-
Crie um Deployment com base no arquivo YAML:
kubectl apply -f https://k8s.io/examples/application/deployment.yaml
-
Exiba informações sobre o Deployment:
kubectl describe deployment nginx-deployment
A saída é semelhante a esta:
Name: nginx-deployment Namespace: default CreationTimestamp: Tue, 30 Aug 2016 18:11:37 -0700 Labels: app=nginx Annotations: deployment.kubernetes.io/revision=1 Selector: app=nginx Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 1 max unavailable, 1 max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.14.2 Port: 80/TCP Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: nginx-deployment-1771418926 (2/2 replicas created) No events.
-
Liste os Pods criados pelo Deployment:
kubectl get pods -l app=nginx
A saída é semelhante a esta:
NAME READY STATUS RESTARTS AGE nginx-deployment-1771418926-7o5ns 1/1 Running 0 16h nginx-deployment-1771418926-r18az 1/1 Running 0 16h
-
Exiba informações sobre um Pod:
kubectl describe pod <pod-name>
onde
<pod-name>
é o nome de um dos seus Pods.
Atualizando o Deployment
Você pode atualizar o Deployment aplicando um novo arquivo YAML. Este arquivo YAML especifica que o Deployment deve ser atualizado para usar o nginx:1.16.1.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.16.1 # Atualiza a versão do nginx de 1.14.2 para 1.16.1
ports:
- containerPort: 80
-
Aplique o novo arquivo YAML:
kubectl apply -f https://k8s.io/examples/application/deployment-update.yaml
-
Observe o Deployment criar Pods com novos nomes e excluir os Pods antigos:
kubectl get pods -l app=nginx
Escalonando a aplicação aumentando a contagem de réplicas
Você pode aumentar o número de Pods no seu Deployment aplicando um novo arquivo YAML. Este arquivo YAML define replicas
como 4, o que especifica que o Deployment deve ter quatro Pods:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 4 # Atualiza a contagem de réplicas de 2 para 4
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.16.1
ports:
- containerPort: 80
-
Aplique o novo arquivo YAML:
kubectl apply -f https://k8s.io/examples/application/deployment-scale.yaml
-
Verifique que o Deployment possui quatro Pods:
kubectl get pods -l app=nginx
A saída é semelhante a esta:
NAME READY STATUS RESTARTS AGE nginx-deployment-148880595-4zdqq 1/1 Running 0 25s nginx-deployment-148880595-6zgi1 1/1 Running 0 25s nginx-deployment-148880595-fxcez 1/1 Running 0 2m nginx-deployment-148880595-rwovn 1/1 Running 0 2m
Excluindo um Deployment
Exclua o Deployment pelo nome:
kubectl delete deployment nginx-deployment
Controladores de Replicação -- a Forma Antiga
A forma preferida de criar uma aplicação replicada é usar um Deployment, que por sua vez utiliza um ReplicaSet. Antes do Deployment e do ReplicaSet serem adicionados ao Kubernetes, aplicações replicadas eram configuradas usando um Controlador de Replicação (ReplicationController).
Próximos passos
- Saiba mais sobre objeto Deployment.
2 - Executar uma Aplicação Com Estado e de Instância Única
Esta página mostra como executar um aplicativo com estado e de instância única no Kubernetes utilizando um PersistentVolume e um Deployment. O aplicativo utilizado é o MySQL.
Objetivos
- Crie um PersistentVolume referenciando um disco no seu ambiente.
- Crie um Deployment do MySQL.
- Exponha o MySQL para outros pods no cluster em um nome DNS conhecido.
Antes de você começar
-
Você precisa ter um cluster do Kubernetes e a ferramenta de linha de comando kubectl deve estar configurada para se comunicar com seu cluster. É recomendado executar esse tutorial em um cluster com pelo menos dois nós que não estejam atuando como hosts de camada de gerenciamento. Se você ainda não possui um cluster, pode criar um usando o minikube ou pode usar um dos seguintes ambientes:
Para verificar a versão, digite
kubectl version
. -
Você precisa ter um provisionador dinâmico de PersistentVolume com uma StorageClass padrão, ou provisionar PersistentVolumes estaticamente por conta própria para atender aos PersistentVolumeClaims utilizados aqui.
Fazer o deploy do MySQL
Você pode executar um aplicativo com estado criando um Deployment do Kubernetes e conectando-o a um PersistentVolume existente usando um PersistentVolumeClaim. Por exemplo, este arquivo YAML descreve um Deployment que executa o MySQL e faz referência ao PersistentVolumeClaim. O arquivo define um volume mount para /var/lib/mysql e, em seguida, cria um PersistentVolumeClaim que procura por um volume de 20G. Essa requisição é atendida por qualquer volume existente que atenda aos requisitos ou por um provisionador dinâmico.
Note: A senha é definida no arquivo de configuração yaml, e isso não é seguro. Veja Secrets do Kubernetes para uma solução segura.
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
clusterIP: None
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:9
name: mysql
env:
# Em cenários reais, utilize um Secret
- name: MYSQL_ROOT_PASSWORD
value: password
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv-volume
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 20Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
-
Faça o deploy do PV e do PVC do arquivo YAML:
kubectl apply -f https://k8s.io/examples/application/mysql/mysql-pv.yaml
-
Faça o deploy do conteúdo do arquivo YAML:
kubectl apply -f https://k8s.io/examples/application/mysql/mysql-deployment.yaml
-
Exiba informações sobre o Deployment:
kubectl describe deployment mysql
A saída é semelhante a esta:
Name: mysql Namespace: default CreationTimestamp: Tue, 01 Nov 2016 11:18:45 -0700 Labels: app=mysql Annotations: deployment.kubernetes.io/revision=1 Selector: app=mysql Replicas: 1 desired | 1 updated | 1 total | 0 available | 1 unavailable StrategyType: Recreate MinReadySeconds: 0 Pod Template: Labels: app=mysql Containers: mysql: Image: mysql:9 Port: 3306/TCP Environment: MYSQL_ROOT_PASSWORD: password Mounts: /var/lib/mysql from mysql-persistent-storage (rw) Volumes: mysql-persistent-storage: Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace) ClaimName: mysql-pv-claim ReadOnly: false Conditions: Type Status Reason ---- ------ ------ Available False MinimumReplicasUnavailable Progressing True ReplicaSetUpdated OldReplicaSets: <none> NewReplicaSet: mysql-63082529 (1/1 replicas created) Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 33s 33s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set mysql-63082529 to 1
-
Liste os pods criados pelo Deployment:
kubectl get pods -l app=mysql
A saída é semelhante a esta:
NAME READY STATUS RESTARTS AGE mysql-63082529-2z3ki 1/1 Running 0 3m
-
Inspecione o PersistentVolumeClaim:
kubectl describe pvc mysql-pv-claim
A saída é semelhante a esta:
Name: mysql-pv-claim Namespace: default StorageClass: Status: Bound Volume: mysql-pv-volume Labels: <none> Annotations: pv.kubernetes.io/bind-completed=yes pv.kubernetes.io/bound-by-controller=yes Capacity: 20Gi Access Modes: RWO Events: <none>
Acessando a instância do MySQL
O arquivo YAML anterior cria um Service que permite que outros Pods no cluster acessem o banco de dados. A opção clusterIP: None
faz com que o nome DNS do Service resolva diretamente para o endereço IP do Pod. Isso é ideal quando você tem apenas um Pod por trás do Service e não pretende aumentar o número de Pods.
Execute um cliente MySQL para se conectar ao servidor:
kubectl run -it --rm --image=mysql:9 --restart=Never mysql-client -- mysql -h mysql -ppassword
Este comando cria um novo Pod no cluster executando um cliente MySQL e o conecta ao servidor por meio do Service. Se a conexão for bem-sucedida, você saberá que seu banco de dados MySQL com estado está em funcionamento.
Waiting for pod default/mysql-client-274442439-zyp6i to be running, status is Pending, pod ready: false
If you don't see a command prompt, try pressing enter.
mysql>
Atualizando
A imagem ou qualquer outra parte do Deployment pode ser atualizada normalmente
com o comando kubectl apply
. Aqui estão algumas precauções específicas para aplicativos com estado:
- Não faça o escalonamento do aplicativo. Esta configuração é apenas para aplicativos de instância única. O PersistentVolume subjacente só pode ser montado em um Pod. Para aplicativos com estado em cluster, consulte a documentação do StatefulSet.
- Use
strategy:
type: Recreate
no arquivo YAML de configuração do Deployment. Isso instrui o Kubernetes a não usar atualizações graduais. Atualizações graduais não funcionarão, pois não é possível ter mais de um Pod em execução ao mesmo tempo. A estratégiaRecreate
irá parar o primeiro Pod antes de criar um novo com a configuração atualizada.
Excluindo um deployment
Exclua os objetos implantados pelo nome:
kubectl delete deployment,svc mysql
kubectl delete pvc mysql-pv-claim
kubectl delete pv mysql-pv-volume
Se você provisionou manualmente um PersistentVolume, também precisará excluí-lo manualmente, assim como liberar o recurso subjacente. Se você usou um provisionador dinâmico, ele exclui automaticamente o PersistentVolume ao detectar que você excluiu o PersistentVolumeClaim. Alguns provisionadores dinâmicos (como os de EBS e PD) também liberam o recurso subjacente ao excluir o PersistentVolume.
Próximos passos
-
Saiba mais sobre objetos Deployment.
-
Saiba mais sobre implantação de aplicativos
3 - Acessando a API do Kubernetes a partir de um Pod
Este guia demonstra como acessar a API do Kubernetes de dentro de um Pod.
Antes de você começar
Você precisa ter um cluster do Kubernetes e a ferramenta de linha de comando kubectl deve estar configurada para se comunicar com seu cluster. É recomendado executar esse tutorial em um cluster com pelo menos dois nós que não estejam atuando como hosts de camada de gerenciamento. Se você ainda não possui um cluster, pode criar um usando o minikube ou pode usar um dos seguintes ambientes:
Acessando a API de dentro de um Pod
Ao acessar a API a partir de um Pod, localizar e autenticar-se no servidor de API são processos ligeiramente diferentes do caso de um cliente externo.
A maneira mais fácil de usar a API do Kubernetes a partir de um Pod é utilizar uma das bibliotecas clientes oficiais. Essas bibliotecas conseguem descobrir automaticamente o servidor de API e autenticar-se.
Usando Bibliotecas Clientes Oficiais
De dentro de um Pod, as formas recomendadas de se conectar à API do Kubernetes são:
-
Para clientes em Go, utilize a biblioteca cliente oficial em Go. A função
rest.InClusterConfig()
lida automaticamente com a descoberta do host da API e a autenticação. Veja um exemplo aqui. -
Para clientes em Python, utilize a biblioteca cliente oficial em Python. A função
config.load_incluster_config()
lida automaticamente com a descoberta do host da API e a autenticação. Veja um exemplo aqui. -
Há diversas outras bibliotecas disponíveis. Consulte a página de Bibliotecas Clientes.
Em todos os casos, as credenciais da conta de serviço do Pod são utilizadas para se comunicar com segurança com o servidor de API.
Acessando diretamente a API REST
Enquanto estiver em execução em um Pod, seu contêiner pode criar uma URL HTTPS para o servidor de API do Kubernetes
obtendo as variáveis de ambiente KUBERNETES_SERVICE_HOST
e KUBERNETES_SERVICE_PORT_HTTPS
.
O endereço do servidor de API dentro do cluster também é publicado em um Service chamado kubernetes
no namespace
default
, para que os Pods possam referenciar kubernetes.default.svc
como um nome DNS para o servidor de API local.
Nota:
O Kubernetes não garante que o servidor de API tenha um certificado válido para o nome de hostkubernetes.default.svc
;
no entanto, espera-se que a camada de gerenciamento apresente um certificado válido para o nome de host ou endereço
IP representado por $KUBERNETES_SERVICE_HOST
.A forma recomendada de autenticar-se no servidor de API é com uma credencial
de conta de serviço.
Por padrão, um Pod é associado a uma conta de serviço, e uma credencial (token) para essa conta de serviço é colocada no
sistema de arquivos de cada contêiner nesse Pod, em /var/run/secrets/kubernetes.io/serviceaccount/token
.
Se disponível, um pacote de certificados é colocado no sistema de arquivos de cada contêiner em /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
,
e deve ser utilizado para verificar o certificado de serviço do servidor de API.
Por fim, o namespace padrão a ser usado para operações da API com escopo de namespace é colocado em um arquivo em
/var/run/secrets/kubernetes.io/serviceaccount/namespace
em cada contêiner.
Usando o kubectl proxy
Se você quiser consultar a API sem utilizar uma biblioteca cliente oficial, pode executar o kubectl proxy
como o comando de um novo contêiner sidecar no Pod.
Dessa forma, o kubectl proxy
irá se autenticar na API e expô-la na interface localhost
do Pod,
permitindo que outros contêineres no Pod a utilizem diretamente.
Sem usar um proxy
É possível evitar o uso do kubectl proxy passando o token de autenticação diretamente para o servidor de API. O certificado interno garante a segurança da conexão.
# Aponte para o nome de host interno do servidor de API
APISERVER=https://kubernetes.default.svc
# Caminho para o token da Conta de Serviço
SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
# Ler o namespace deste Pod
NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)
# Ler o token de portador da Conta de Serviço
TOKEN=$(cat ${SERVICEACCOUNT}/token)
# Referenciar a autoridade certificadora (CA) interna
CACERT=${SERVICEACCOUNT}/ca.crt
# Explorar a API com o TOKEN
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api
A saída será semelhante a esta:
{
"kind": "APIVersions",
"versions": ["v1"],
"serverAddressByClientCIDRs": [
{
"clientCIDR": "0.0.0.0/0",
"serverAddress": "10.0.1.149:443"
}
]
}