Merge pull request #353 from akram/0.4-openshift-docs
Adding OpenShift doc
This commit is contained in:
		
						commit
						55cfdf5687
					
				|  | @ -0,0 +1,8 @@ | |||
| KUBERNETES_PROVIDER=crc | ||||
| DOCKER_ORGANIZATION=image-registry.openshift-image-registry.svc:5000/jenkins-operator | ||||
| DOCKER_REGISTRY=kubernetes-operator | ||||
| IMAGE_PULL_MODE=remote | ||||
| JENKINS_API_PORT=0 | ||||
| JENKINS_API_USE_NODEPORT=false | ||||
| NAMESPACE=$(oc project -q) | ||||
| 
 | ||||
|  | @ -7,64 +7,67 @@ metadata: | |||
| spec: | ||||
|   master: | ||||
|     containers: | ||||
|       - name: jenkins-master | ||||
|         command: | ||||
|           - /usr/bin/go-init | ||||
|           - '-main' | ||||
|           - /usr/libexec/s2i/run | ||||
|         env: | ||||
|           - name: OPENSHIFT_ENABLE_OAUTH | ||||
|             value: 'true' | ||||
|           - name: OPENSHIFT_ENABLE_REDIRECT_PROMPT | ||||
|             value: 'true' | ||||
|           - name: DISABLE_ADMINISTRATIVE_MONITORS | ||||
|             value: 'false' | ||||
|           - name: KUBERNETES_MASTER | ||||
|             value: 'https://kubernetes.default:443' | ||||
|           - name: KUBERNETES_TRUST_CERTIFICATES | ||||
|             value: 'true' | ||||
|           - name: JENKINS_SERVICE_NAME | ||||
|             value: jenkins-operator-http-example | ||||
|           - name: JNLP_SERVICE_NAME | ||||
|             value: jenkins-operator-slave-example | ||||
|           - name: JENKINS_UC_INSECURE | ||||
|             value: 'false' | ||||
|           - name: JENKINS_HOME | ||||
|             value: /var/lib/jenkins | ||||
|           - name: JAVA_OPTS | ||||
|             value: >- | ||||
|               -XX:+UnlockExperimentalVMOptions -XX:+UnlockExperimentalVMOptions | ||||
|               -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 | ||||
|               -Djenkins.install.runSetupWizard=false -Djava.awt.headless=true | ||||
|         image: 'quay.io/openshift/origin-jenkins:latest' | ||||
|         imagePullPolicy: Always | ||||
|         livenessProbe: | ||||
|           httpGet: | ||||
|             path: /login | ||||
|             port: 8080 | ||||
|             scheme: HTTP | ||||
|           initialDelaySeconds: 420 | ||||
|           periodSeconds: 360 | ||||
|           timeoutSeconds: 240 | ||||
|         readinessProbe: | ||||
|           httpGet: | ||||
|             path: /login | ||||
|             port: 8080 | ||||
|             scheme: HTTP | ||||
|           initialDelaySeconds: 3 | ||||
|           periodSeconds: 0 | ||||
|           timeoutSeconds: 240 | ||||
|         resources: | ||||
|           limits: | ||||
|             cpu: 600m | ||||
|             memory: 4Gi | ||||
|           requests: | ||||
|             cpu: 500m | ||||
|             memory: 3Gi | ||||
|     - name: jenkins-master | ||||
|       command: | ||||
|       - /usr/bin/go-init | ||||
|       - '-main' | ||||
|       - /usr/libexec/s2i/run | ||||
|       env: | ||||
|       - name: OPENSHIFT_ENABLE_OAUTH | ||||
|         value: 'true' | ||||
|       - name: OPENSHIFT_ENABLE_REDIRECT_PROMPT | ||||
|         value: 'true' | ||||
|       - name: DISABLE_ADMINISTRATIVE_MONITORS | ||||
|         value: 'false' | ||||
|       - name: KUBERNETES_MASTER | ||||
|         value: 'https://kubernetes.default:443' | ||||
|       - name: KUBERNETES_TRUST_CERTIFICATES | ||||
|         value: 'true' | ||||
|       - name: JENKINS_SERVICE_NAME | ||||
|         value: jenkins-operator-http-jenkins | ||||
|       - name: JNLP_SERVICE_NAME | ||||
|         value: jenkins-operator-slave-jenkins | ||||
|       - name: JENKINS_UC_INSECURE | ||||
|         value: 'false' | ||||
|       - name: JENKINS_HOME | ||||
|         value: /var/lib/jenkins | ||||
|       - name: JAVA_OPTS | ||||
|         value: >- | ||||
|           -XX:+UnlockExperimentalVMOptions -XX:+UnlockExperimentalVMOptions | ||||
|           -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 | ||||
|           -Djenkins.install.runSetupWizard=false -Djava.awt.headless=true | ||||
|       image: 'quay.io/openshift/origin-jenkins:latest' | ||||
|       imagePullPolicy: Always | ||||
|       livenessProbe: | ||||
|         httpGet: | ||||
|           path: /login | ||||
|           port: 8080 | ||||
|           scheme: HTTP | ||||
|         initialDelaySeconds: 420 | ||||
|         periodSeconds: 360 | ||||
|         timeoutSeconds: 240 | ||||
|       readinessProbe: | ||||
|         httpGet: | ||||
|           path: /login | ||||
|           port: 8080 | ||||
|           scheme: HTTP | ||||
|         initialDelaySeconds: 3 | ||||
|         periodSeconds: 0 | ||||
|         timeoutSeconds: 240 | ||||
|       resources: | ||||
|         limits: | ||||
|           cpu: 600m | ||||
|           memory: 4Gi | ||||
|         requests: | ||||
|           cpu: 500m | ||||
|           memory: 3Gi | ||||
|   service: | ||||
|     port: 8080 | ||||
|     type: ClusterIP | ||||
|   slaveService: | ||||
|     port: 50000 | ||||
|     type: ClusterIP | ||||
| 
 | ||||
|   serviceAccount: | ||||
|     annotations: | ||||
|       serviceaccounts.openshift.io/oauth-redirectreference.jenkins: '{"kind":"OAuthRedirectReference","apiVersion":"v1","reference":{"kind":"Route","name":"jenkins-operator"}}' | ||||
|      | ||||
|  |  | |||
|  | @ -767,7 +767,12 @@ func TestEnsureExtraRBAC(t *testing.T) { | |||
| 				Roles: []rbacv1.RoleRef{}, | ||||
| 			}, | ||||
| 		} | ||||
| 		reconciler := New(configuration.Configuration{Client: fakeClient, Jenkins: jenkins, Scheme: scheme.Scheme}, nil, client.JenkinsAPIConnectionSettings{}) | ||||
| 		config := configuration.Configuration{ | ||||
| 			Client:  fakeClient, | ||||
| 			Jenkins: jenkins, | ||||
| 			Scheme:  scheme.Scheme, | ||||
| 		} | ||||
| 		reconciler := New(config, log.Log, client.JenkinsAPIConnectionSettings{}) | ||||
| 		metaObject := resources.NewResourceObjectMeta(jenkins) | ||||
| 
 | ||||
| 		// when
 | ||||
|  | @ -803,7 +808,12 @@ func TestEnsureExtraRBAC(t *testing.T) { | |||
| 				}, | ||||
| 			}, | ||||
| 		} | ||||
| 		reconciler := New(configuration.Configuration{Client: fakeClient, Jenkins: jenkins, Scheme: scheme.Scheme}, nil, client.JenkinsAPIConnectionSettings{}) | ||||
| 		config := configuration.Configuration{ | ||||
| 			Client:  fakeClient, | ||||
| 			Jenkins: jenkins, | ||||
| 			Scheme:  scheme.Scheme, | ||||
| 		} | ||||
| 		reconciler := New(config, log.Log, client.JenkinsAPIConnectionSettings{}) | ||||
| 		metaObject := resources.NewResourceObjectMeta(jenkins) | ||||
| 
 | ||||
| 		// when
 | ||||
|  | @ -845,7 +855,12 @@ func TestEnsureExtraRBAC(t *testing.T) { | |||
| 				}, | ||||
| 			}, | ||||
| 		} | ||||
| 		reconciler := New(configuration.Configuration{Client: fakeClient, Jenkins: jenkins, Scheme: scheme.Scheme}, nil, client.JenkinsAPIConnectionSettings{}) | ||||
| 		config := configuration.Configuration{ | ||||
| 			Client:  fakeClient, | ||||
| 			Jenkins: jenkins, | ||||
| 			Scheme:  scheme.Scheme, | ||||
| 		} | ||||
| 		reconciler := New(config, log.Log, client.JenkinsAPIConnectionSettings{}) | ||||
| 		metaObject := resources.NewResourceObjectMeta(jenkins) | ||||
| 
 | ||||
| 		// when
 | ||||
|  | @ -888,7 +903,12 @@ func TestEnsureExtraRBAC(t *testing.T) { | |||
| 				}, | ||||
| 			}, | ||||
| 		} | ||||
| 		reconciler := New(configuration.Configuration{Client: fakeClient, Jenkins: jenkins, Scheme: scheme.Scheme}, log.Log, client.JenkinsAPIConnectionSettings{}) | ||||
| 		config := configuration.Configuration{ | ||||
| 			Client:  fakeClient, | ||||
| 			Jenkins: jenkins, | ||||
| 			Scheme:  scheme.Scheme, | ||||
| 		} | ||||
| 		reconciler := New(config, log.Log, client.JenkinsAPIConnectionSettings{}) | ||||
| 		metaObject := resources.NewResourceObjectMeta(jenkins) | ||||
| 
 | ||||
| 		// when
 | ||||
|  |  | |||
|  | @ -6,17 +6,19 @@ import ( | |||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	createVerb        = "create" | ||||
| 	deleteVerb        = "delete" | ||||
| 	getVerb           = "get" | ||||
| 	listVerb          = "list" | ||||
| 	watchVerb         = "watch" | ||||
| 	patchVerb         = "patch" | ||||
| 	updateVerb        = "update" | ||||
| 	EmptyApiGroups    = "" | ||||
| 	OpenshiftApiGroup = "image.openshift.io" | ||||
| 	BuildApiGroup     = "build.openshift.io" | ||||
| 
 | ||||
| 	createVerb = "create" | ||||
| 	deleteVerb = "delete" | ||||
| 	getVerb    = "get" | ||||
| 	listVerb   = "list" | ||||
| 	watchVerb  = "watch" | ||||
| 	patchVerb  = "patch" | ||||
| 	updateVerb = "update" | ||||
| 	//EmptyAPIGroup short hand for the empty API group while defining policies
 | ||||
| 	EmptyAPIGroup = "" | ||||
| 	//OpenshiftAPIGroup the openshift api group name
 | ||||
| 	OpenshiftAPIGroup = "image.openshift.io" | ||||
| 	//BuildAPIGroup  the openshift api group name for builds
 | ||||
| 	BuildAPIGroup = "build.openshift.io" | ||||
| ) | ||||
| 
 | ||||
| // NewRole returns rbac role for jenkins master
 | ||||
|  | @ -54,22 +56,23 @@ func NewRoleBinding(name, namespace, serviceAccountName string, roleRef v1.RoleR | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // NewDefaultPolicyRules sets the default policy rules
 | ||||
| func NewDefaultPolicyRules() []v1.PolicyRule { | ||||
| 	var rules []v1.PolicyRule | ||||
| 	ReadOnly := []string{getVerb, listVerb, watchVerb} | ||||
| 	Default  := []string{createVerb, deleteVerb, getVerb, listVerb, patchVerb, updateVerb, watchVerb} | ||||
| 	Create   := []string{createVerb} | ||||
| 	Default := []string{createVerb, deleteVerb, getVerb, listVerb, patchVerb, updateVerb, watchVerb} | ||||
| 	Create := []string{createVerb} | ||||
| 
 | ||||
| 	rules = append(rules,  NewPolicyRule(EmptyApiGroups, "pods/portforward", Create)) | ||||
| 	rules = append(rules,  NewPolicyRule(EmptyApiGroups, "pods", Default)) | ||||
| 	rules = append(rules,  NewPolicyRule(EmptyApiGroups, "pods/exec", Default)) | ||||
| 	rules = append(rules,  NewPolicyRule(EmptyApiGroups, "configmaps", ReadOnly)) | ||||
| 	rules = append(rules,  NewPolicyRule(EmptyApiGroups, "pods/log", ReadOnly)) | ||||
| 	rules = append(rules,  NewPolicyRule(EmptyApiGroups, "secrets", ReadOnly)) | ||||
| 	rules = append(rules, NewPolicyRule(EmptyAPIGroup, "pods/portforward", Create)) | ||||
| 	rules = append(rules, NewPolicyRule(EmptyAPIGroup, "pods", Default)) | ||||
| 	rules = append(rules, NewPolicyRule(EmptyAPIGroup, "pods/exec", Default)) | ||||
| 	rules = append(rules, NewPolicyRule(EmptyAPIGroup, "configmaps", ReadOnly)) | ||||
| 	rules = append(rules, NewPolicyRule(EmptyAPIGroup, "pods/log", ReadOnly)) | ||||
| 	rules = append(rules, NewPolicyRule(EmptyAPIGroup, "secrets", ReadOnly)) | ||||
| 
 | ||||
| 	rules = append(rules,  NewOpenShiftPolicyRule(OpenshiftApiGroup, "imagestreams", ReadOnly)) | ||||
| 	rules = append(rules,  NewOpenShiftPolicyRule(BuildApiGroup, "buildconfigs", ReadOnly)) | ||||
| 	rules = append(rules,  NewOpenShiftPolicyRule(BuildApiGroup, "builds", ReadOnly)) | ||||
| 	rules = append(rules, NewOpenShiftPolicyRule(OpenshiftAPIGroup, "imagestreams", ReadOnly)) | ||||
| 	rules = append(rules, NewOpenShiftPolicyRule(BuildAPIGroup, "buildconfigs", ReadOnly)) | ||||
| 	rules = append(rules, NewOpenShiftPolicyRule(BuildAPIGroup, "builds", ReadOnly)) | ||||
| 
 | ||||
| 	return rules | ||||
| } | ||||
|  | @ -84,8 +87,7 @@ func NewPolicyRule(apiGroup string, resource string, verbs []string) v1.PolicyRu | |||
| 	return rule | ||||
| } | ||||
| 
 | ||||
| // NewPolicyRule returns a policyRule allowing verbs on resources
 | ||||
| // NewOpenShiftPolicyRule returns a policyRule allowing verbs on resources
 | ||||
| func NewOpenShiftPolicyRule(apiGroup string, resource string, verbs []string) v1.PolicyRule { | ||||
| 	return NewPolicyRule(apiGroup,resource,verbs) | ||||
| 	return NewPolicyRule(apiGroup, resource, verbs) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,8 +2,10 @@ package base | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/base/resources" | ||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/log" | ||||
| 
 | ||||
| 	stackerr "github.com/pkg/errors" | ||||
| 	corev1 "k8s.io/api/core/v1" | ||||
|  | @ -15,8 +17,11 @@ import ( | |||
| func (r *ReconcileJenkinsBaseConfiguration) createServiceAccount(meta metav1.ObjectMeta) error { | ||||
| 	serviceAccount := &corev1.ServiceAccount{} | ||||
| 	err := r.Client.Get(context.TODO(), types.NamespacedName{Name: meta.Name, Namespace: meta.Namespace}, serviceAccount) | ||||
| 	annotations := r.Configuration.Jenkins.Spec.ServiceAccount.Annotations | ||||
| 	msg := fmt.Sprintf("createServiceAccount with annotations %v", annotations) | ||||
| 	r.logger.V(log.VDebug).Info(msg) | ||||
| 	if err != nil && apierrors.IsNotFound(err) { | ||||
| 		serviceAccount = resources.NewServiceAccount(meta, r.Configuration.Jenkins.Spec.ServiceAccount.Annotations) | ||||
| 		serviceAccount = resources.NewServiceAccount(meta, annotations) | ||||
| 		if err = r.CreateResource(serviceAccount); err != nil { | ||||
| 			return stackerr.WithStack(err) | ||||
| 		} | ||||
|  | @ -24,11 +29,11 @@ func (r *ReconcileJenkinsBaseConfiguration) createServiceAccount(meta metav1.Obj | |||
| 		return stackerr.WithStack(err) | ||||
| 	} | ||||
| 
 | ||||
| 	if !compareMap(r.Configuration.Jenkins.Spec.ServiceAccount.Annotations, serviceAccount.Annotations) { | ||||
| 	if !compareMap(annotations, serviceAccount.Annotations) { | ||||
| 		if serviceAccount.Annotations == nil { | ||||
| 			serviceAccount.Annotations = map[string]string{} | ||||
| 		} | ||||
| 		for key, value := range r.Configuration.Jenkins.Spec.ServiceAccount.Annotations { | ||||
| 		for key, value := range annotations { | ||||
| 			serviceAccount.Annotations[key] = value | ||||
| 		} | ||||
| 		if err = r.UpdateResource(serviceAccount); err != nil { | ||||
|  |  | |||
|  | @ -0,0 +1,104 @@ | |||
| --- | ||||
| title: "OpenShift" | ||||
| linkTitle: "OpenShift" | ||||
| weight: 20 | ||||
| date: 2020-04-29 | ||||
| description: > | ||||
|     Additional configuration for OpenShift | ||||
| --- | ||||
| 
 | ||||
| ## SecurityContext | ||||
| 
 | ||||
| OpenShift enforces Security Constraints Context (scc) when deploying an image. | ||||
| By default, container images run in restricted scc which prevents from setting | ||||
| a fixed user id to run with. You need to have ensure that you do not provide a | ||||
| securityContext with a runAsUser and that your image does not use a hardcoded user. | ||||
| 
 | ||||
| ```yaml | ||||
| securityContext: {} | ||||
| ``` | ||||
| 
 | ||||
| ## OpenShift Jenkins image | ||||
| 
 | ||||
| OpenShift provides a pre-configured Jenkins image containing  3 openshift plugins for | ||||
| jenkins (openshift-login-plugin, openshift-sync-plugin and openshift-client-plugin) | ||||
| which allows better jenkins integration with kubernetes and OpenShift. | ||||
| 
 | ||||
| The OpenShift Jenkins image requires additional configuration to be fully enabled. | ||||
| 
 | ||||
| ### Sample OpenShift CR | ||||
| The following Custom Resource can be used to create a Jenkins instance using the   | ||||
| OpenShift Jenkins image and sets values for: | ||||
| - `image: 'quay.io/openshift/origin-jenkins:latest' : This is the OpenShift Jenkins image. | ||||
| 
 | ||||
| - serviceAccount: to allow oauth authentication to work, the service account needs | ||||
| a specific annotation pointing to the route exposing the jenkins service. Here, | ||||
| the route is named `jenkins-route` | ||||
| 
 | ||||
| - `OPENSHIFT_ENABLE_OAUTH` environment variable for the master container is set to true. | ||||
| 
 | ||||
| Here is a complete Jenkins CR allowing the deployment of the Jenkins OpenShift image. | ||||
| ```yaml | ||||
| apiVersion: jenkins.io/v1alpha2 | ||||
| kind: Jenkins | ||||
| metadata: | ||||
|   annotations: | ||||
|     jenkins.io/openshift-mode: 'true' | ||||
|   name: jenkins | ||||
| spec: | ||||
|   serviceAccount: | ||||
|     annotations: | ||||
|       serviceaccounts.openshift.io/oauth-redirectreference.jenkins: '{"kind":"OAuthRedirectReference","apiVersion":"v1","reference":{"kind":"Route","name":"jenkins-route"}}' | ||||
|   master: | ||||
|     containers: | ||||
|     - name: jenkins-master | ||||
|       image: 'quay.io/openshift/origin-jenkins:latest' | ||||
|       command: | ||||
|       - /usr/bin/go-init | ||||
|       - '-main' | ||||
|       - /usr/libexec/s2i/run | ||||
|       env: | ||||
|       - name: OPENSHIFT_ENABLE_OAUTH | ||||
|         value: 'true' | ||||
|       - name: OPENSHIFT_ENABLE_REDIRECT_PROMPT | ||||
|         value: 'true' | ||||
|       - name: DISABLE_ADMINISTRATIVE_MONITORS | ||||
|         value: 'false' | ||||
|       - name: KUBERNETES_MASTER | ||||
|         value: 'https://kubernetes.default:443' | ||||
|       - name: KUBERNETES_TRUST_CERTIFICATES | ||||
|         value: 'true' | ||||
|       - name: JENKINS_SERVICE_NAME | ||||
|         value: jenkins-operator-http-jenkins | ||||
|       - name: JNLP_SERVICE_NAME | ||||
|         value: jenkins-operator-slave-jenkins | ||||
|       - name: JENKINS_UC_INSECURE | ||||
|         value: 'false' | ||||
|       - name: JENKINS_HOME | ||||
|         value: /var/lib/jenkins | ||||
|       - name: JAVA_OPTS | ||||
|         value: >- | ||||
|           -XX:+UnlockExperimentalVMOptions -XX:+UnlockExperimentalVMOptions | ||||
|           -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 | ||||
|           -Djenkins.install.runSetupWizard=false -Djava.awt.headless=true | ||||
|       imagePullPolicy: Always | ||||
|   service: | ||||
|     port: 8080 | ||||
|     type: ClusterIP | ||||
|   slaveService: | ||||
|     port: 50000 | ||||
|     type: ClusterIP | ||||
| ``` | ||||
| 
 | ||||
| ### OpenShift OAuth integration | ||||
| The creation of a Route is required for the integraiton of Jenkins with | ||||
| OpenShift oauth authentication. By default, the jenkins http service is named | ||||
| `jenkins-operator-http-${jenkins-cr-name}` | ||||
| 
 | ||||
| ```bash | ||||
| oc create route edge jenkins-route --service=jenkins-operator-http-jenkins | ||||
| ``` | ||||
| Note: the route name (jenkins-route) must match the pointed route on the serviceaccount annotation. | ||||
| 
 | ||||
| 
 | ||||
| After the creation of the Route. It can be used to navigate to the Jenkins Login Page and login with your Openshift Credentials. | ||||
		Loading…
	
		Reference in New Issue