Deployments

This document helps you get OPA up and running in different deployment environments. You should read this document if you are planning to deploy OPA.

Docker

Docker makes OPA easy to deploy in different types of environments.

This section explains how to use the official OPA Docker images. If this is your first time deploying OPA and you plan to use one of the Docker images, we recommend you review this section to familiarize yourself with the basics.

OPA releases are available as images on Docker Hub.

Running with Docker

If you start OPA outside of Docker without any arguments, it prints a list of available commands. By default, the official OPA Docker image executes the run command which starts an instance of OPA as an interactive shell. This is nice for development, however, for deployments, we want to run OPA as a server.

The run command accepts a --server (or -s) flag that starts OPA as a server. See --help for more information on other arguments. The most important command line arguments for OPA’s server mode are:

  • --addr to set the listening address (default: 0.0.0.0:8181).
  • --log-level (or -l) to set the log level (default: "info").
  • --log-format to set the log format (default: "json").

By default, OPA listens for normal HTTP connections on 0.0.0.0:8181. To make OPA listen for HTTPS connections, see Security.

We can run OPA as a server using Docker:

  1. docker run -p 8181:8181 openpolicyagent/opa \
  2. run --server --log-level debug

Test that OPA is available:

  1. curl -i localhost:8181/

Logging

OPA logs to stderr and the level can be set with --log-level/-l. The default log level is info which causes OPA to log request/response information.

  1. {"client_addr":"[::1]:64427","level":"debug","msg":"Received request.","req_body":"","req_id":1,"req_method":"GET","req_params":{},"req_path":"/v1/data","time":"20.7.13-11T18:22:18-08:00"}
  2. {"client_addr":"[::1]:64427","level":"debug","msg":"Sent response.","req_id":1,"req_method":"GET","req_path":"/v1/data","resp_bytes":13,"resp_duration":0.392554,"resp_status":200,"time":"20.7.13-11T18:22:18-08:00"}

If the log level is set to debug the request and response message bodies will be logged. This is useful for development however it can be expensive in production.

  1. {"addrs":[":8181"],"insecure_addr":"","level":"info","msg":"First line of log stream.","time":"2019-05-08T17:25:26-07:00"}
  2. {"level":"info","msg":"Starting decision log uploader.","plugin":"decision_logs","time":"2019-05-08T17:25:26-07:00"}
  3. {"client_addr":"[::1]:63902","level":"info","msg":"Received request.","req_body":"","req_id":1,"req_method":"GET","req_params":{},"req_path":"/v1/data","time":"2019-05-08T17:25:41-07:00"}
  4. {"client_addr":"[::1]:63902","level":"info","msg":"Sent response.","req_id":1,"req_method":"GET","req_path":"/v1/data","resp_body":"{\"decision_id\":\"f4b41501-2408-4a14-8269-1c1085abeda4\",\"result\":{}}","resp_bytes":66,"resp_duration":2.545972,"resp_status":200,"time":"2019-05-08T17:25:41-07:00"}

The default log format is json and intended for production use. For more human readable formats use “json-pretty” or “text”.

Note: The text log format is not performance optimized or intended for production use.

Volume Mounts

By default, OPA does not include any data or policies.

The simplest way to load data and policies into OPA is to provide them via the file system as command line arguments. When running inside Docker, you can provide files via volume mounts.

  1. docker run -v $PWD:/example openpolicyagent/opa eval --data /example 'data.example.greeting'

$PWD/example/[data.json](https://github.com/open-policy-agent/opa/tree/master/docs/code/deployments-docker/example/data.json)

  1. {
  2. "hostOS": "$(uname)"
  3. }

$PWD/example/[policy.rego](https://github.com/open-policy-agent/opa/tree/master/docs/code/deployments-docker/example/data.json/deployments-docker/example/policy.rego)

  1. package example
  2. greeting = msg {
  3. msg := concat("", ["Hello ", data.example.hostOS, "!"])
  4. }

More Information

For more information on OPA’s command line, see --help:

  1. docker run openpolicyagent/opa run --help

Tagging

The Docker Hub repository contains tags for every release of OPA. For more information on each release see the GitHub Releases page.

The “latest” tag refers to the most recent release. The latest tag is convenient if you want to quickly try out OPA however for production deployments, we recommend using an explicit version tag.

Development builds are also available on Docker Hub. For each version the {version}-dev tag refers the most recent development build for that version.

The version information is contained in the OPA executable itself. You can check the version with the following command:

  1. docker run openpolicyagent/opa version

Kubernetes

Kicking the Tires

This section shows how to quickly deploy OPA on top of Kubernetes to try it out.

If you are interested in using OPA to enforce admission control policies in Kubernetes, see the Kubernetes Admission Control Tutorial and Kubernetes Admission Control Guide pages.

These steps assume Kubernetes is deployed with minikube. If you are using a different Kubernetes provider, the steps should be similar. You may need to use a different Service configuration at the end.

First, create a ConfigMap containing a test policy.

In this case, the policy file does not contain sensitive information so it’s fine to store as a ConfigMap. If the file contained sensitive information, then we recommend you store it as a Secret.

example.rego

  1. package example
  2. greeting = msg {
  3. info := opa.runtime()
  4. hostname := info.env["HOSTNAME"] # Kubernetes sets the HOSTNAME environment variable.
  5. msg := sprintf("hello from pod %q!", [hostname])
  6. }
  1. kubectl create configmap example-policy --from-file example.rego

Next, create a Deployment to run OPA. The ConfigMap containing the policy is volume mounted into the container. This allows OPA to load the policy from the file system.

deployment-opa.yaml:

  1. apiVersion: extensions/v1beta1
  2. kind: Deployment
  3. metadata:
  4. name: opa
  5. labels:
  6. app: opa
  7. spec:
  8. replicas: 1
  9. template:
  10. metadata:
  11. labels:
  12. app: opa
  13. name: opa
  14. spec:
  15. containers:
  16. - name: opa
  17. image: openpolicyagent/opa:0.11.0
  18. ports:
  19. - name: http
  20. containerPort: 8181
  21. args:
  22. - "run"
  23. - "--ignore=.*" # exclude hidden dirs created by Kubernetes
  24. - "--server"
  25. - "/policies"
  26. volumeMounts:
  27. - readOnly: true
  28. mountPath: /policies
  29. name: example-policy
  30. volumes:
  31. - name: example-policy
  32. configMap:
  33. name: example-policy
  1. kubectl create -f deployment-opa.yaml

At this point OPA is up and running. Create a Service to expose the OPA API so that you can query it:

service-opa.yaml

  1. kind: Service
  2. apiVersion: v1
  3. metadata:
  4. name: opa
  5. labels:
  6. app: opa
  7. spec:
  8. type: NodePort
  9. selector:
  10. app: opa
  11. ports:
  12. - name: http
  13. protocol: TCP
  14. port: 8181
  15. targetPort: 8181
  1. kubectl create -f service-opa.yaml

Get the URL of OPA using minikube:

  1. OPA_URL=$(minikube service opa --url)

Now you can query OPA’s API:

  1. curl $OPA_URL/v1/data

OPA will respond with the greeting from the policy (the pod hostname will differ):

  1. {
  2. "result": {
  3. "example": {
  4. "greeting": "hello from pod \"opa-78ccdfddd-xplxr\"!"
  5. }
  6. }
  7. }

Readiness and Liveness Probes

OPA exposes a /health API endpoint that you can configure Kubernetes Readiness and Liveness Probes to call. For example:

  1. containers:
  2. - name: opa
  3. image: openpolicyagent/opa:0.11.0
  4. ports:
  5. - name: http
  6. containerPort: 8181
  7. args:
  8. - "run"
  9. - "--ignore=.*" # exclude hidden dirs created by Kubernetes
  10. - "--server"
  11. - "/policies"
  12. volumeMounts:
  13. - readOnly: true
  14. mountPath: /policies
  15. name: example-policy
  16. livenessProbe:
  17. httpGet:
  18. scheme: HTTP # assumes OPA listens on localhost:8181
  19. port: 8181
  20. initialDelaySeconds: 5 # tune these periods for your environemnt
  21. periodSeconds: 5
  22. readinessProbe:
  23. httpGet:
  24. path: /health?bundle=true # Include bundle activation in readiness
  25. scheme: HTTP
  26. port: 8181
  27. initialDelaySeconds: 5
  28. periodSeconds: 5

See the Health API documentation for more detail on the /health API endpoint.

HTTP Proxies

OPA uses the standard Go net/http package for outbound HTTP requests that download bundles, upload decision logs, etc. In environments where an HTTP proxy is required, you can configure OPA using the pseudo-standard HTTP_PROXY, HTTPS_PROXY, and NO_PROXY environment variables.