Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@

## [Unreleased]

## Changed
### Changed

- Startup probe created and thresholds in liveness and readiness probes fine-tuned ([#193]).
- Include chart name when installing with a custom release name ([#209], [#210]).
- Orphaned resources are deleted ([#215]).
- Fix HBase-shell start failure ([#218]).
- Add integration tests and usage documentation for Phoenix ([#221]).
- Added OpenShift compatiblity ([#232])

[#193]: https://github.com/stackabletech/hbase-operator/pull/193
[#209]: https://github.com/stackabletech/hbase-operator/pull/209
[#210]: https://github.com/stackabletech/hbase-operator/pull/210
[#215]: https://github.com/stackabletech/hbase-operator/pull/215
[#218]: https://github.com/stackabletech/hbase-operator/pull/218
[#221]: https://github.com/stackabletech/hbase-operator/pull/221
[#232]: https://github.com/stackabletech/hbase-operator/pull/232

## [0.3.0] - 2022-06-30

Expand All @@ -28,7 +30,7 @@
a single namespace to watch ([#137]).
- Writing a discovery config map containing `hbase-site.xml` with the `hbase.zookeeper.quorum` property ([#163]).

## Changed
### Changed

- `operator-rs` `0.12.0` -> `0.15.0` ([#137], [#153]).
- Now using HDFS discovery config map instead of hdfs name node config map ([#153])
Expand All @@ -55,13 +57,9 @@
### Changed

- `operator-rs` `0.10.0` -> `0.12.0` ([#127]).

[#127]: https://github.com/stackabletech/hbase-operator/pull/127

### Changed

- Migrated to StatefulSet rather than direct Pod management ([#110]).

[#127]: https://github.com/stackabletech/hbase-operator/pull/127
[#110]: https://github.com/stackabletech/hbase-operator/pull/110

## [0.1.0] - 2021-10-28
Expand Down
83 changes: 83 additions & 0 deletions deploy/helm/hbase-operator/templates/roles.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,86 @@ rules:
- {{ include "operator.name" . }}clusters/status
verbs:
- patch
- apiGroups:
- rbac.authorization.k8s.io
resources:
- clusterroles
verbs:
- bind
resourceNames:
- {{ include "operator.name" . }}-clusterrole

{{ if .Capabilities.APIVersions.Has "security.openshift.io/v1" }}
---
apiVersion: security.openshift.io/v1
kind: SecurityContextConstraints
metadata:
name: hbase-scc
annotations:
kubernetes.io/description: |-
This resource is derived from hostmount-anyuid. It provides all the features of the
restricted SCC but allows host mounts and any UID by a pod. This is primarily
used by the persistent volume recycler. WARNING: this SCC allows host file
system access as any UID, including UID 0. Grant with caution.
release.openshift.io/create-only: "true"
allowHostDirVolumePlugin: true
allowHostIPC: false
allowHostNetwork: false
allowHostPID: false
allowHostPorts: false
allowPrivilegeEscalation: true
allowPrivilegedContainer: false
allowedCapabilities: null
defaultAddCapabilities: null
fsGroup:
type: RunAsAny
groups: []
priority: null
readOnlyRootFilesystem: false
runAsUser:
type: RunAsAny
seLinuxContext:
type: MustRunAs
supplementalGroups:
type: RunAsAny
volumes:
- configMap
- downwardAPI
- emptyDir
- hostPath
- nfs
- persistentVolumeClaim
- projected
- secret
- ephemeral
{{ end }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "operator.name" . }}-clusterrole
rules:
- apiGroups:
- ""
resources:
- configmaps
- secrets
- serviceaccounts
verbs:
- get
- apiGroups:
- events.k8s.io
resources:
- events
verbs:
- create
{{ if .Capabilities.APIVersions.Has "security.openshift.io/v1" }}
- apiGroups:
- security.openshift.io
resources:
- securitycontextconstraints
resourceNames:
- hbase-scc
verbs:
- use
{{ end }}
28 changes: 28 additions & 0 deletions deploy/manifests/roles.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,31 @@ rules:
- hbaseclusters/status
verbs:
- patch
- apiGroups:
- rbac.authorization.k8s.io
resources:
- clusterroles
verbs:
- bind
resourceNames:
- hbase-clusterrole
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: hbase-clusterrole
rules:
- apiGroups:
- ""
resources:
- configmaps
- secrets
- serviceaccounts
verbs:
- get
- apiGroups:
- events.k8s.io
resources:
- events
verbs:
- create
47 changes: 44 additions & 3 deletions rust/operator-binary/src/hbase_controller.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
//! Ensures that `Pod`s are configured and running for each [`HbaseCluster`]

use crate::discovery::build_discovery_configmap;
use crate::{discovery::build_discovery_configmap, rbac};
use snafu::{OptionExt, ResultExt, Snafu};
use stackable_hbase_crd::{
HbaseCluster, HbaseConfig, HbaseRole, APP_NAME, HBASE_ENV_SH, HBASE_MASTER_PORT,
HBASE_REGIONSERVER_PORT, HBASE_REST_PORT, HBASE_SITE_XML, HBASE_ZOOKEEPER_QUORUM,
};
use stackable_operator::{
builder::{ConfigMapBuilder, ContainerBuilder, ObjectMetaBuilder, PodBuilder},
builder::{
ConfigMapBuilder, ContainerBuilder, ObjectMetaBuilder, PodBuilder,
PodSecurityContextBuilder,
},
cluster_resources::ClusterResources,
k8s_openapi::{
api::{
Expand Down Expand Up @@ -124,6 +127,16 @@ pub enum Error {
entry: &'static str,
cm_name: String,
},
#[snafu(display("failed to patch service account: {source}"))]
ApplyServiceAccount {
name: String,
source: stackable_operator::error::Error,
},
#[snafu(display("failed to patch role binding: {source}"))]
ApplyRoleBinding {
name: String,
source: stackable_operator::error::Error,
},
}

type Result<T, E = Error> = std::result::Result<T, E>;
Expand Down Expand Up @@ -182,6 +195,20 @@ pub async fn reconcile_hbase(hbase: Arc<HbaseCluster>, ctx: Arc<Ctx>) -> Result<
.await
.context(ApplyDiscoveryConfigMapSnafu)?;

let (rbac_sa, rbac_rolebinding) = rbac::build_rbac_resources(hbase.as_ref(), "hbase");
client
.apply_patch(CONTROLLER_NAME, &rbac_sa, &rbac_sa)
.await
.with_context(|_| ApplyServiceAccountSnafu {
name: rbac_sa.name_unchecked(),
})?;
client
.apply_patch(CONTROLLER_NAME, &rbac_rolebinding, &rbac_rolebinding)
.await
.with_context(|_| ApplyRoleBindingSnafu {
name: rbac_rolebinding.name_unchecked(),
})?;

for (role_name, group_config) in validated_config.iter() {
for (rolegroup_name, rolegroup_config) in group_config.iter() {
let rolegroup = hbase.server_rolegroup_ref(role_name, rolegroup_name);
Expand All @@ -192,7 +219,12 @@ pub async fn reconcile_hbase(hbase: Arc<HbaseCluster>, ctx: Arc<Ctx>) -> Result<
rolegroup_config,
&zk_connect_string,
)?;
let rg_statefulset = build_rolegroup_statefulset(&hbase, &rolegroup, rolegroup_config)?;
let rg_statefulset = build_rolegroup_statefulset(
&hbase,
&rolegroup,
rolegroup_config,
&rbac_sa.name_unchecked(),
)?;
cluster_resources
.add(client, &rg_service)
.await
Expand Down Expand Up @@ -383,6 +415,7 @@ fn build_rolegroup_statefulset(
hbase: &HbaseCluster,
rolegroup_ref: &RoleGroupRef<HbaseCluster>,
_rolegroup_config: &HashMap<PropertyNameKind, BTreeMap<String, String>>,
sa_name: &str,
) -> Result<StatefulSet> {
let hbase_version = hbase_version(hbase)?;

Expand Down Expand Up @@ -541,6 +574,14 @@ fn build_rolegroup_statefulset(
}),
..Default::default()
})
.service_account_name(sa_name)
.security_context(
PodSecurityContextBuilder::new()
.run_as_user(rbac::HBASE_UID)
.run_as_group(0)
.fs_group(1000) // Needed for secret-operator
.build(),
)
.build_template(),
..StatefulSetSpec::default()
}),
Expand Down
1 change: 1 addition & 0 deletions rust/operator-binary/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod discovery;
mod hbase_controller;
mod rbac;

use std::sync::Arc;

Expand Down
44 changes: 44 additions & 0 deletions rust/operator-binary/src/rbac.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use stackable_operator::builder::ObjectMetaBuilder;
use stackable_operator::k8s_openapi::api::core::v1::ServiceAccount;
use stackable_operator::k8s_openapi::api::rbac::v1::{RoleBinding, RoleRef, Subject};
use stackable_operator::kube::{Resource, ResourceExt};

/// Used as runAsUser in the pod security context. This is specified in the Hbase image file
pub const HBASE_UID: i64 = 1000;

/// Build RBAC objects for the product workloads.
/// The `rbac_prefix` is meant to be the product name, for example: zookeeper, airflow, etc.
/// and it is a assumed that a ClusterRole named `{rbac_prefix}-clusterrole` exists.
pub fn build_rbac_resources<T: Resource>(
resource: &T,
rbac_prefix: &str,
) -> (ServiceAccount, RoleBinding) {
let sa_name = format!("{rbac_prefix}-sa");
let service_account = ServiceAccount {
metadata: ObjectMetaBuilder::new()
.name_and_namespace(resource)
.name(sa_name.clone())
.build(),
..ServiceAccount::default()
};

let role_binding = RoleBinding {
metadata: ObjectMetaBuilder::new()
.name_and_namespace(resource)
.name(format!("{rbac_prefix}-rolebinding"))
.build(),
role_ref: RoleRef {
kind: "ClusterRole".to_string(),
name: format!("{rbac_prefix}-clusterrole"),
api_group: "rbac.authorization.k8s.io".to_string(),
},
subjects: Some(vec![Subject {
kind: "ServiceAccount".to_string(),
name: sa_name,
namespace: resource.namespace(),
..Subject::default()
}]),
};

(service_account, role_binding)
}