This page details methods of exposing Appian sites outside of Kubernetes for self-managed customers. Specifically, it allows you to expose the Webapp component or Apache Web Server (httpd) component (if enabled) so that Appian can send and receive web traffic. It should be used in conjunction with Restricting Traffic as a security measure.
If you've enabled network policies via the .spec.networkPolicies.enabled field on Appian custom resources, make sure to also refer to the Restricting Traffic page.
The Appian operator and Appian custom resource definition (CRD) support exposing Appian sites outside of Kubernetes via NodePort Services with the .spec.service field on Appian custom resources.
Specifically, the .spec.service.type
field can be set to NodePort
to instruct the operator to change the Service it creates from a ClusterIP
Service to a NodePort
Service. The nodePort
field can also be used to specify the port on each node on which the Service should be exposed (for example, the Service's .spec.ports[0].nodePort
field).
If you expect users to enter the node port in their browser, you must ensure that the port number is specified via the .spec.webapp.url field and .spec.webapp.staticUrl and .spec.webapp.dynamicUrl fields, if applicable. In this scenario, it is required to specify the nodePort
field because the port number assigned by the system is not known ahead of time otherwise.
If running multiple Webapp replicas and Apache Web Server (httpd) is disabled, you may need to enable session affinity at the Kubernetes layer. This can be done by changing the sessionAffinity
field to ClientIP
from its default value of None
. In this case, session affinity can be further tuned via the sessionAffinityConfig
field.
If you are using ExternalDNS to synchronize exposed Kubernetes Services and Ingresses with your DNS provider, you may also wish to set the external-dns.alpha.kubernetes.io/hostname
annotation on the created Service resource (for more info on this annotation, see the FAQ in the ExternalDNS docs). This can be done via the annotations
field.
The following custom resource snippet defines an Appian site with Apache Web Server (httpd) disabled and multiple Webapp replicas exposed on port 30000 on each node via a NodePort
Service:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: crd.k8s.appian.com/v1alpha1
kind: Appian
metadata:
name: appian-k8s-nodeport
spec:
webapp:
url: http://appian.example.com:30000
staticUrl: http://appian.example-static.com:30000
dynamicUrl: http://appian.example-dynamic.com:30000
replicas: 3
service:
annotations:
external-dns.alpha.kubernetes.io/hostname: "appian.example.com,appian.example-static.com,appian.example-dynamic.com"
type: NodePort
nodePort: 30000
sessionAffinity: ClientIP
The Appian operator and Appian custom resource definition (CRD) support exposing Appian sites outside of Kubernetes via LoadBalancer Services with the .spec.service field on Appian custom resources.
Specifically, the .spec.service.type
field can be set to LoadBalancer
to instruct the operator to change the Service it creates from a ClusterIP
Service to a LoadBalancer
Service. The port
field can be used to specify the port that will be exposed by the Service (for example, the Service's .spec.ports[0].port
field). The loadBalancerIP
field can be used to specify a specific IP with which the load balancer should be created. The nodePort
field can also be used to specify the port on each node on which the Service should be exposed (for example, the Service's .spec.ports[0].nodePort
field).
If running multiple Webapp replicas and Apache Web Server (httpd) is disabled, you may need to enable session affinity at the Kubernetes layer. This can be done by changing the sessionAffinity
field to ClientIP
from its default value of None
. In this case, session affinity can be further tuned via the sessionAffinityConfig
field.
In some environments, including AWS, enabling session affinity for LoadBalancer
Services is prohibited.
If you are using ExternalDNS to synchronize exposed Kubernetes Services and Ingresses with your DNS provider, you may also wish to set the external-dns.alpha.kubernetes.io/hostname
annotation on the created Service resource (for more info on this annotation, see the FAQ in the ExternalDNS docs). This can be done via the annotations
field.
The subsections below detail custom resource snippets that show how to expose Appian sites via LoadBalancer
Services on AWS (implementing on other providers is not yet available).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
apiVersion: crd.k8s.appian.com/v1alpha1
kind: Appian
metadata:
name: appian-k8s-aws-loadbalancer
spec:
webapp:
url: https://appian.example.com
staticUrl: https://appian.example-static.com
dynamicUrl: https://appian.example-dynamic.com
service:
annotations:
external-dns.alpha.kubernetes.io/hostname: "appian.example.com,appian.example-static.com,appian.example-dynamic.com"
# Enable TLS/SSL support by specifying an SSL certificate and negotiation
# policy. The backend protocol must be set to http since neither Webapp
# nor Apache Web Server (httpd) speak HTTPS/SSL
# https://kubernetes.io/docs/concepts/services-networking/service/#ssl-support-on-aws
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:<REGION>:<ACCOUNT_ID>:certificate/<CERTIFICATE_ID>
service.beta.kubernetes.io/aws-load-balancer-ssl-negotiation-policy: ELBSecurityPolicy-TLS-1-2-2017-01
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http
# Enables operations in Appian with delayed responses, such as application
# import inspection in Appian Designer, by increasing the time, in
# seconds, that the connection is allowed to be idle (no data has been
# sent over the connection) before it is closed by the load balancer
# https://kubernetes.io/docs/concepts/services-networking/service/#other-elb-annotations
service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "300"
type: LoadBalancer
# So that the created load balancer listens on port 443
port: 443
The Appian operator and Appian custom resource definition (CRD) support enabling and configuring Ingress for Appian sites via the .spec.ingress field on Appian custom resources.
To enable Ingress for a given site, set .spec.ingress.enabled
to true
. To set annotations on the created Ingress resource, define .spec.ingress.annotations
.
The operator does not support the new IngressClass resource and ingressClassName
field added in Kubernetes v1.18. Users must instead specify the deprecated kubernetes.io/ingress.class annotation.
The operator does not yet support spec.DefaultBackend
and pathType
added in Kubernetes v1.22.
An Ingress controller is responsible for fulfilling the Ingress. Appian sites in Kubernetes should work with a variety of Ingress controllers provided both the Ingress resource and controller are properly configured. The subsection below details how to configure Ingress via Appian custom resources for NGINX.
Like many Ingress controllers, NGINX Ingress supports specifying annotations on Ingress resources to customize their behavior.
All Appian sites exposed via NGINX Ingress require the following annotations:
1
2
3
4
5
6
7
8
9
10
# Enables large file uploads in Appian by disabling client request body size
# checks
# https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#custom-max-body-size
nginx.ingress.kubernetes.io/proxy-body-size: "0"
# Enables operations in Appian with delayed responses, such as application
# import inspection in Appian Designer, by increasing the timeout for reading a
# response from the proxied server
# https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#custom-timeouts
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
Appian sites with Apache Web Server (httpd) disabled (the default) also require the following annotations:
1
2
3
4
5
# Enables redirects from / to /<APPLICATION_CONTEXT> where <APPLICATION_CONTEXT>
# is defined by .spec.webapp.applicationContext - defaulting to suite if
# undefined
# https://kubernetes.github.io/ingress-nginx/examples/rewrite/
nginx.ingress.kubernetes.io/app-root: /suite
Appian sites with Apache Web Server (httpd) disabled (the default) and .spec.service.protocol set to ajp
instead of the default value of http
also require the following annotations:
1
2
3
4
# Changes the backend protocol from HTTP to Apache JServ Protocol (AJP) since
# Ingress traffic routes to Tomcat's AJP connector
# https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#backend-protocol
nginx.ingress.kubernetes.io/backend-protocol: AJP
Appian sites with Apache Web Server (httpd) disabled (the default) and multiple Webapp replicas also require the following annotations:
1
2
3
4
5
# Enables cookie-based session affinity and disables rebalancing sessions to new
# servers
# https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#session-affinity
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/affinity-mode: persistent
Finally, Appian sites with Apache Web Server (httpd) enabled also require the following annotations:
1
2
3
4
5
6
# Suppresses an issue where Apache Web Server (httpd) returns temporary
# redirects to http:// by setting the text that should be changed in the
# Location and Refresh header fields of a proxied server response
# https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#proxy-redirect
nginx.ingress.kubernetes.io/proxy-redirect-from: http://
nginx.ingress.kubernetes.io/proxy-redirect-to: https://
Additional annotations may be required depending on your specific use case. For a full list of annotations supported by NGINX Ingress, refer to its documentation.