Container Immutability
O que isso significa?
O container não será modificado durante seu tempo de vida. Nada será adicionado ou removido do container. Caso seja necessário outra imagem será criada com a devida modificação e uma nova instância será criada.
A vantagem dessa abordagem é que sempre sabemos o estado em que o container se encontra. Entrar em uma aplicação e alterar uma configuração não será possível replicar novamente.
Container imutáveis nos permite:
- Utilizar métodos avançados de deployment
- Facilidade no rollback
- Maior confiabilidade
- Melhor segurança (em nível de container), pois sempre podemos criar um novo tendo certeza que não existe nenhuma processo malicioso rodando.
A imutabilidade e a facilidade de queimar novas imagens é um dos motivos que tornaram os containers tão populares.
O que podemos fazer para ter certeza que os containers estão imutáveis.
- Remover bash/shell para que não seja possível iteragir com o container.
- Tornar o file system read only para que não seja possívei escrever
- Rodar com um usuário e não com o root.
Isso é o que manda as boas práticas e como fazer o hardening de um container.
Mas e se não tivermos o controle das imagens dos containers? Nesse caso sempre é possível utilizar a image como base e alterar gerando uma nova.
Se ainda sim não for possível é possível fazer algumas coisas.
Podemos alterar o command e passar todos os comandos que quisermos e por ultimos chamar o comando que rodará o container.
containers:
- image: nginx
name: nginx
# recomendo toda permissão de escrita recursivamente antes de chamar o executavel do nginx
command:
- "chmod a-w -R / && nginx"
resources: {}
Ainda podemos resolver isso usando o startup probe que é bem similar ao readness ou liveness probes, porém esses dois últimos somente irão ser executados depois que o startup probe obtiver sucesso caso contrário o container ficará restartando todo tempo. Desta forma não precisaremos nem conhecer o entrypoint do container.
containers:
- image: nginx
name: nginx
startupProbe:
exec:
command:
- chmod
- a-w -R /
initialDelaySeconds: 1
periodSeconds: 5
Esses método acima são possíveis, mas não é por que é possível que devermos fazer isso.
A melhor maneira seria impor read only no /root usando o SecurityContext e ou PodSecurityPolicies.
containers:
- image: httpd
name: httpd
securityContext:
readOnlyRootFilesystem: true
Porém esse pod irá precisar escrever em /usr/local/apache2/logs. Quando isso acontecer podemos montar um emptyDir.
containers:
- image: httpd
name: httpd
securityContext:
readOnlyRootFilesystem: true
volumeMounts:
- mountPath: /usr/local/apache2/logs
name: logs
volumes:
- name: logs
emptyDir: {}
Se transportamos isso para o mundo do docker seria como executar o comando abaixo.
docker run --read-only --tmpfs /run my-container
Ainda poderíamos usar o recurso do init container que inicia antes da aplicação, prepara o terreno e somente depois que termina será disparado o container da aplicação. Se o init container preparar o volume que será usado pela aplicação dando a ela somente recursos de leitura pode ser um bom cenário.

Obviamente é necessaário proteger que usuários mudam o spec de um pod usando RBAC.