Skip to content

Commit

Permalink
operator: Add memberlist IPv6 support (grafana#10562)
Browse files Browse the repository at this point in the history
Co-authored-by: Joao Marcal <joao.marcal12@gmail.com>
Co-authored-by: Robert Jacob <xperimental@solidproject.de>
  • Loading branch information
3 people committed Oct 2, 2023
1 parent 85d49e7 commit 17925a8
Show file tree
Hide file tree
Showing 17 changed files with 426 additions and 7 deletions.
1 change: 1 addition & 0 deletions operator/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Release 5.6.12

- [10562](https://github.com/grafana/loki/pull/10562) **periklis**: Add memberlist IPv6 support
- [10600](https://github.com/grafana/loki/pull/10600) **periklis**: Update Loki operand to v2.9.1

## Release 5.6.11
Expand Down
10 changes: 10 additions & 0 deletions operator/apis/loki/v1/lokistack_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,16 @@ type MemberListSpec struct {
// +kubebuilder:validation:optional
// +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:select:default","urn:alm:descriptor:com.tectonic.ui:select:podIP"},displayName="Instance Address"
InstanceAddrType InstanceAddrType `json:"instanceAddrType,omitempty"`

// EnableIPv6 enables IPv6 support for the memberlist based hash ring.
//
// Currently this also forces the instanceAddrType to podIP to avoid local address lookup
// for the memberlist.
//
// +optional
// +kubebuilder:validation:Optional
// +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors="urn:alm:descriptor:com.tectonic.ui:booleanSwitch",displayName="Enable IPv6"
EnableIPv6 bool `json:"enableIPv6,omitempty"`
}

// HashRingSpec defines the hash ring configuration
Expand Down
26 changes: 26 additions & 0 deletions operator/apis/loki/v1/lokistack_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ func (r *LokiStack) validate(old *LokiStack) error {
allErrs = append(allErrs, errors...)
}

errors = r.Spec.validateHashRingSpec()
if len(errors) != 0 {
allErrs = append(allErrs, errors...)
}
if len(allErrs) == 0 {
return nil
}
Expand All @@ -158,6 +162,28 @@ func (r *LokiStack) validate(old *LokiStack) error {
)
}

func (s *LokiStackSpec) validateHashRingSpec() field.ErrorList {
if s.HashRing == nil {
return nil
}

if s.HashRing.MemberList == nil {
return nil
}

if s.HashRing.MemberList.EnableIPv6 && s.HashRing.MemberList.InstanceAddrType == InstanceAddrDefault {
return field.ErrorList{
field.Invalid(
field.NewPath("spec", "hashRing", "memberlist", "instanceAddrType"),
s.HashRing.MemberList.InstanceAddrType,
ErrIPv6InstanceAddrTypeNotAllowed.Error(),
),
}
}

return nil
}

// buildAppliedSchemaMap creates a map of schemas which occur before the given time
func buildAppliedSchemaMap(schemas []ObjectStorageSchema, effectiveDate time.Time) objectStorageSchemaMap {
appliedMap := objectStorageSchemaMap{}
Expand Down
33 changes: 33 additions & 0 deletions operator/apis/loki/v1/lokistack_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,39 @@ var ltt = []struct {
},
),
},
{
desc: "using default InstanceAddrType and enableIPv6",
spec: v1.LokiStack{
Spec: v1.LokiStackSpec{
HashRing: &v1.HashRingSpec{
Type: v1.HashRingMemberList,
MemberList: &v1.MemberListSpec{
EnableIPv6: true,
InstanceAddrType: v1.InstanceAddrDefault,
},
},
Storage: v1.ObjectStorageSpec{
Schemas: []v1.ObjectStorageSchema{
{
Version: v1.ObjectStorageSchemaV12,
EffectiveDate: "2020-10-11",
},
},
},
},
},
err: apierrors.NewInvalid(
schema.GroupKind{Group: "loki.grafana.com", Kind: "LokiStack"},
"testing-stack",
field.ErrorList{
field.Invalid(
field.NewPath("spec", "hashRing", "memberlist", "instanceAddrType"),
v1.InstanceAddrDefault,
v1.ErrIPv6InstanceAddrTypeNotAllowed.Error(),
),
},
),
},
}

func TestLokiStackValidationWebhook_ValidateCreate(t *testing.T) {
Expand Down
2 changes: 2 additions & 0 deletions operator/apis/loki/v1/v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ var (
ErrSchemaRetroactivelyRemoved = errors.New("Cannot retroactively remove schema(s)")
// ErrSchemaRetroactivelyChanged when a schema has been retroactively changed
ErrSchemaRetroactivelyChanged = errors.New("Cannot retroactively change schema")
// ErrIPv6InstanceAddrTypeNotAllowed when the default InstanceAddrType is used with enableIPv6.
ErrIPv6InstanceAddrTypeNotAllowed = errors.New(`instanceAddrType "default" cannot be used with enableIPv6 at the same time`)
)
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,13 @@ spec:
- description: MemberList configuration spec
displayName: Memberlist Config
path: hashRing.memberlist
- description: "EnableIPv6 enables IPv6 support for the memberlist based hash
ring. \n Currently this also forces the instanceAddrType to podIP to avoid
local address lookup for the memberlist."
displayName: Enable IPv6
path: hashRing.memberlist.enableIPv6
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:booleanSwitch
- description: InstanceAddrType defines the type of address to use to advertise
to the ring. Defaults to the first address from any private network interfaces
of the current pod. Alternatively the public pod IP can be used in case
Expand Down
5 changes: 5 additions & 0 deletions operator/bundle/manifests/loki.grafana.com_lokistacks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ spec:
memberlist:
description: MemberList configuration spec
properties:
enableIPv6:
description: "EnableIPv6 enables IPv6 support for the memberlist
based hash ring. \n Currently this also forces the instanceAddrType
to podIP to avoid local address lookup for the memberlist."
type: boolean
instanceAddrType:
description: InstanceAddrType defines the type of address
to use to advertise to the ring. Defaults to the first address
Expand Down
5 changes: 5 additions & 0 deletions operator/config/crd/bases/loki.grafana.com_lokistacks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ spec:
memberlist:
description: MemberList configuration spec
properties:
enableIPv6:
description: "EnableIPv6 enables IPv6 support for the memberlist
based hash ring. \n Currently this also forces the instanceAddrType
to podIP to avoid local address lookup for the memberlist."
type: boolean
instanceAddrType:
description: InstanceAddrType defines the type of address
to use to advertise to the ring. Defaults to the first address
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ spec:
- description: MemberList configuration spec
displayName: Memberlist Config
path: hashRing.memberlist
- description: "EnableIPv6 enables IPv6 support for the memberlist based hash
ring. \n Currently this also forces the instanceAddrType to podIP to avoid
local address lookup for the memberlist."
displayName: Enable IPv6
path: hashRing.memberlist.enableIPv6
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:booleanSwitch
- description: InstanceAddrType defines the type of address to use to advertise
to the ring. Defaults to the first address from any private network interfaces
of the current pod. Alternatively the public pod IP can be used in case
Expand Down
14 changes: 14 additions & 0 deletions operator/docs/operator/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1348,6 +1348,20 @@ Alternatively the public pod IP can be used in case private networks (RFC 1918 a
are not available.</p>
</td>
</tr>
<tr>
<td>
<code>enableIPv6</code><br/>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>EnableIPv6 enables IPv6 support for the memberlist based hash ring.</p>
<p>Currently this also forces the instanceAddrType to podIP to avoid local address lookup
for the memberlist.</p>
</td>
</tr>
</tbody>
</table>

Expand Down
16 changes: 14 additions & 2 deletions operator/internal/manifests/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,19 +194,31 @@ func alertManagerConfig(s *lokiv1beta1.AlertManagerSpec) *config.AlertManagerCon
}

func gossipRingConfig(stackName, stackNs string, spec *lokiv1.HashRingSpec) config.GossipRing {
var instanceAddr string
var (
instanceAddr string
enableIPv6 bool
)
if spec != nil && spec.Type == lokiv1.HashRingMemberList && spec.MemberList != nil {
switch spec.MemberList.InstanceAddrType {
case lokiv1.InstanceAddrPodIP:
instanceAddr = fmt.Sprintf("${%s}", gossipInstanceAddrEnvVarName)
instanceAddr = gossipInstanceAddrEnvVarTemplate
case lokiv1.InstanceAddrDefault:
// Do nothing use loki defaults
default:
// Do nothing use loki defaults
}

// Always default to use the pod IP address when IPv6 enabled to ensure:
// - On Single Stack IPv6: Skip interface checking
// - On Dual Stack IPv4/6: Eliminate duplicate memberlist node registration
if spec.MemberList.EnableIPv6 {
enableIPv6 = true
instanceAddr = gossipInstanceAddrEnvVarTemplate
}
}

return config.GossipRing{
EnableIPv6: enableIPv6,
InstanceAddr: instanceAddr,
InstancePort: grpcPort,
BindPort: gossipPort,
Expand Down
37 changes: 37 additions & 0 deletions operator/internal/manifests/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,43 @@ func TestConfigOptions_GossipRingConfig(t *testing.T) {
MembersDiscoveryAddr: "my-stack-gossip-ring.my-ns.svc.cluster.local",
},
},
{
desc: "IPv6 enabled with default instance address type",
spec: lokiv1.LokiStackSpec{
HashRing: &lokiv1.HashRingSpec{
Type: lokiv1.HashRingMemberList,
MemberList: &lokiv1.MemberListSpec{
EnableIPv6: true,
},
},
},
wantOptions: config.GossipRing{
EnableIPv6: true,
InstanceAddr: "${HASH_RING_INSTANCE_ADDR}",
InstancePort: 9095,
BindPort: 7946,
MembersDiscoveryAddr: "my-stack-gossip-ring.my-ns.svc.cluster.local",
},
},
{
desc: "IPv6 enabled with podIP instance address type",
spec: lokiv1.LokiStackSpec{
HashRing: &lokiv1.HashRingSpec{
Type: lokiv1.HashRingMemberList,
MemberList: &lokiv1.MemberListSpec{
EnableIPv6: true,
InstanceAddrType: lokiv1.InstanceAddrPodIP,
},
},
},
wantOptions: config.GossipRing{
EnableIPv6: true,
InstanceAddr: "${HASH_RING_INSTANCE_ADDR}",
InstancePort: 9095,
BindPort: 7946,
MembersDiscoveryAddr: "my-stack-gossip-ring.my-ns.svc.cluster.local",
},
},
}
for _, tc := range tt {
tc := tc
Expand Down
Loading

0 comments on commit 17925a8

Please sign in to comment.