Escrito por

Artigo Evandro Wendt · Maio 24 4m read

Implantando o IRIS for Health no OpenShift

Caso você esteja planejando implantar o IRIS for Health, ou qualquer um dos nossos produtos conteinerizados, via IKO no OpenShift, gostaria de compartilhar alguns dos obstáculos que tivemos que superar.

Como em qualquer instalação baseada no IKO, primeiro precisamos implantar o próprio IKO. No entanto, estávamos recebendo este erro:

Warning FailedCreate 75s (x16 over 3m59s) replicaset-controller Error creating: pods "intersystems-iris-operator-amd-f6757dcc-" is forbidden: unable to validate against any security context constraint:

seguido por uma lista de todos os Security Context Constraints (SCCs) com os quais ele não conseguiu validar.

Se você for como eu, pode se surpreender ao ver esse tipo de erro ao implantar no Kubernetes, porque um Security Context Constraint não é um objeto do Kubernetes. Isso vem do universo do OpenShift, que estende a definição padrão do Kubernetes (leia mais sobre isso aqui).

O que acontece é que, quando instalamos o IKO via Helm (veja mais sobre como fazer isso aqui), criamos uma service account.

[Contas de usuário são para pessoas. Service accounts são para processos de aplicação — documentação do Kubernetes].

Essa service account fica responsável por criar objetos, como o pod do IKO. No entanto, isso falha.

O OpenShift possui uma ampla gama de permissões de segurança que podem ser restritas, e uma forma de fazer isso é por meio de Security Context Constraints.

O que precisávamos fazer era criar o seguinte SecurityContextConstraint:

# Create SCC for ISC resources
kind: SecurityContextConstraints
apiVersion: security.openshift.io/v1
metadata:
  name: iris-scc
  namespace: <iris namespace>
allowPrivilegedContainer: false
runAsUser:
  type: RunAsAny
seLinuxContext:
  type: RunAsAny
fsGroup:
  type: RunAsAny
supplementalGroups:
  type: RunAsAny
allowHostNetwork: false
allowHostPID: false
allowHostPorts: false
allowHostDirVolumePlugin: false
allowHostIPC: false
readOnlyRootFilesystem: false
allowPrivilegeEscalation: false
users:
  - system:serviceaccount:<iris namespace>:intersystems-iris-operator-amd

Isso concede acesso à service account intersystems-iris-operator-amd para criar objetos, permitindo que ela valide contra o iris-scc.

Em seguida, precisamos fazer o deploy do próprio IrisCluster (mais detalhes aqui). No entanto, isso também estava falhando, porque precisávamos conceder à service account default acesso ao SCC anyuid, permitindo que nossos containers fossem executados como qualquer usuário (mais especificamente, precisamos permitir que o usuário irisowner/51773 execute os containers!).

Fazemos isso da seguinte forma:

ocm adm policy add-scc-to-user anyuid -z default -n <iris namespace>

Em seguida, criamos um rolebinding para a role Admin associada à service account intersystems-iris-operator-amd, concedendo a ela a capacidade de criar e monitorar recursos no namespace. No OpenShift, isso pode ser feito pela interface web (console) ou conforme explicado emkubectl create rolebinding.

Um último detalhe importante é que você pode perceber que o container recebe um SIGKILL, como mostrado no IRIS Messages Log:

Initializing IRIS, please wait...
Merging IRIS, please wait...
Starting IRIS
Startup aborted.
Unexpected failure: The target process received a termination signal 9.
Operation aborted.
[ERROR] Command "iris start IRIS quietly" exited with status 256

Isso pode ocorrer devido a Resource Quotas e Limit Ranges. Lembre-se de que essas restrições existem tanto no nível do pod quanto no nível do container.

Espero que isso ajude, e boa implantação!

P.S.

Você pode ter notado que, no arquivo values.yaml do chart Helm, existe este trecho:

serviceAccount:
  # Specifies whether a ServiceAccount should be created
  create: true
  # The name of the ServiceAccount to use.
  # If not set and create is true, a name is generated using the fullname template
  name:

Na verdade, você pode editar isso e utilizar uma service account que já exista. Por exemplo:

serviceAccount:
  # Specifies whether a ServiceAccount should be created
  create: false
  # The name of the ServiceAccount to use.
  # If not set and create is true, a name is generated using the fullname template
  name: myExistingServiceAccount

Observe que isso não é uma solução universal, mas pode ajudar caso você esteja implantando em um ambiente mais restritivo, onde não é permitido criar service accounts, mas é possível utilizar algumas que já existem.