2020年2月19日 | by 明远

Kubernetes 中优化流量和安全性需要注意的7点要求

根据 Portworx 在2018年进行的一项调查,五分之四的企业现在正在使用容器,其中83%的企业正在生产环境中使用。而这个数字在2017年只有67%,很明显,容器不仅仅是一种时尚。
但是,随着容器的流行,一些公司开始在 Kubernetes 内建立有效的流量控制和安全策略。
作为容器调度和集群管理平台,Kubernetes 致力于提供出色的基础架构,因此被无数公司采用。它刚刚开源五周年,最近在福布斯发表的一篇名为《Kubernetes “the most popular open source …

2020年2月19日 | by 灵雀云

Angular 实践:如何优雅地发起和处理请求

Tips: 本文实现重度依赖 ObservableInput,灵感来自灵雀云同事实现的 asyncData 指令,但之前没有 ObservableInput 的装饰器,处理响应 Input 变更相对麻烦一些,所以这里使用 ObservableInput 重新实现。

What And Why

pic1.jpg

大部分情况下处理请求有如下几个过程:

看着很复杂的样子,既要 Loading,又要 Reload,还要 Retry,如果用命令式写法可能会很蛋疼,要处理各种分支,而今天要讲的 rxAsync 指令就是用来优雅地解决这个问题的。

How

我们来思考下如果解决这个问题,至少有如下四个点需要考虑。

1.发起请求有如下三种情况:
第一次渲染主动加载
用户点击重新加载
加载出错自动重试

2.渲染的过程中需要根据请求的三种状态 —— loading, success, error (类似 Promise 的 pending, resolved, rejected) —— 动态渲染不同的内容

3.输入的参数发生变化时我们需要根据最新参数重新发起请求,但是当用户输入的重试次数变化时应该忽略,因为重试次数只影响 Error 状态

4.用户点击重新加载可能在我们的指令内部,也可能在指令外部

Show Me the Code

话不多说,上代码:

@Directive({
selector: '[rxAsync]',
})
export class AsyncDirective
implements OnInit, OnDestroy {
@ObservableInput()
@Input('rxAsyncContext')
private context$!: Observable // 自定义 fetcher 调用时的 this 上下文,还可以通过箭头函数、fetcher.bind(this) 等方式解决

@ObservableInput()
@Input('rxAsyncFetcher')
private fetcher$!: Observable>> // 自动发起请求的回调函数,参数是下面的 params,应该返回 Observable

@ObservableInput()
@Input('rxAsyncParams')
private params$!: Observable

 // fetcher 调用时传入的参数

@Input('rxAsyncRefetch')
private refetch$$ = new Subject() // 支持用户在指令外部重新发起请求,用户可能不需要,所以设置一个默认值

@ObservableInput()
@Input('rxAsyncRetryTimes')
private retryTimes$!: Observable // 发送 Error 时自动重试的次数,默认不重试

private destroy$$ = new Subject()
private reload$$ = new Subject()

private context = {
reload: this.reload.bind(this), // 将 reload 绑定到 template 上下文中,方便用户在指令内重新发起请求
} as IAsyncDirectiveContext

private viewRef: Nullable
private sub: Nullable

constructor(
private templateRef: TemplateRef,
private viewContainerRef: ViewContainerRef,
) {}

reload() {
this.reload$$.next()
}

ngOnInit() {
// 得益于 ObservableInput ,我们可以一次性响应所有参数的变化
combineLatest([
  this.context$,
  this.fetcher$,
  this.params$,
  this.refetch$$.pipe(startWith(null)), // 需要 startWith(null) 触发第一次请求
  this.reload$$.pipe(startWith(null)), // 同上
])
  .pipe(
    takeUntil(this.destroy$$),
    withLatestFrom(this.retryTimes$), // 忽略 retryTimes 的变更,我们只需要取得它的最新值即可
  )
  .subscribe(([[context, fetcher, params], retryTimes]) => {
    // 如果参数变化且上次请求还没有完成时,自动取消请求忽略掉
    this.disposeSub()

    // 每次发起请求前都重置 loading 和 error 的状态
    Object.assign(this.context, {
      loading: true,
      error: null,
    })

    this.sub = fetcher
      .call(context, params)
      .pipe(
        retry(retryTimes), // 错误时重试
        finalize(() => {
          // 无论是成功还是失败,都取消 loading,并重新触发渲染
          this.context.loading = false
          if (this.viewRef) {
            this.viewRef.detectChanges()
          }
        }),
      )
      .subscribe(
        data => (this.context.$implicit = data),
        error => (this.context.error = error),
      )

    if (this.viewRef) {
      return this.viewRef.markForCheck()
    }

    this.viewRef = this.viewContainerRef.createEmbeddedView(
      this.templateRef,
      this.context,
    )
  })
}

ngOnDestroy() {
this.disposeSub()

this.destroy$$.next()
this.destroy$$.complete()

if (this.viewRef) {
  this.viewRef.destroy()
  this.viewRef = null
}
}

disposeSub() {
if (this.sub) {
  this.sub.unsubscribe()
  this.sub = null
}
}

}

Usage

总共 100 多行的源码,说是很优雅,那到底使用的时候优不优雅呢?来个实例看看:

@Component({
selector: 'rx-async-directive-demo',
template: `

  *rxAsync="
    let todo;
    let loading = loading;
    let error = error;
    let reload = reload;
    context: context;
    fetcher: fetchTodo;
    params: todoId;
    refetch: refetch$$;
    retryTimes: retryTimes
  "
>
  
  loading: {{ loading }} error: {{ error | json }}
  

  todo: {{ todo | json }}

`,
preserveWhitespaces: false,
changeDetection: ChangeDetectionStrategy.OnPush,
})
class AsyncDirectiveComponent {
context = this

@Input()
todoId = 1

@Input()
retryTimes = 0

refetch$$ = new Subject()

constructor(private http: HttpClient) {}

fetchTodo(todoId: string) {
return typeof todoId === 'number'
  ? this.http.get('//jsonplaceholder.typicode.com/todos/' + todoId)
  : EMPTY
}

}

    2020年2月19日 | by Alex Woodie

    MR3 Unleashes Hive on Kubernetes

    Organizations that want to take advantage of the latest capabilities in Apache Hive but don’t want to deal with painful Hadoop upgrades or difficult LLAP configurations have another option in the form of MR3, a new execution engine for Hive that runs natively on Hadoop and Kubernetes. MR3 is a software offering developed by DataMonad, Read more…

    The post MR3 Unleashes Hive on Kubernetes appeared first on Datanami.

    2020年2月19日 | by Kevin Petrie

    Becoming an Event-Driven Enterprise

    Events drive modern business. A website click, a credit card swipe, the turn of a gear – almost any event now can be digitized to create business value. Enterprises that analyze events as they happen are more agile and compete more effectively than those that do not. Event-driven enterprises can increase revenue, reduce cost, and Read more…

    The post Becoming an Event-Driven Enterprise appeared first on Datanami.

    2020年2月18日 | by Colin Clark

    Gen. Hyten On The New American Way of War: All-Domain Operations

    All-Domain Operations is”the biggest key to the future of the entire budget,” the Vice-Chairman of the Joint Chiefs said, “because if we figure that out, we’ll have a significant advantage over everybody in the world for a long time.”

    2020年2月18日 | by Rancher

    实例演示:如何在Kubernetes上大规模运行CI/CD

    本周四晚上8:30,第二期k3s在线培训如约开播!本期课程将介绍k3s的核心架构,如高可用架构以及containerd。一起来进阶探索k3s吧!

    报名及观看链接:http://z-mz.cn/PmwZ

    本文来自Rancher Labs

    在云原生领域中,Kubernetes累积了大量用例。它能够在云中部署应用容器、安排批处理job、处理工作负载以及执行逐步升级。Kubernetes使用高效的编排算法来处理这些操作,即便是大规模集群这些算法依旧表现良好。

    此外,Kubernetes主要用例之一是运行持续集成或持续交付(CI/CD)流水线。也就是说,我们部署一个CI/CD容器的唯一实例,该实例将监控代码版本控制系统。所以,每当我们推送到该仓库时,该容器都会运行流水线步骤。其最终目标是达到一个“true or false”的状态。True即在集成阶段commit通过了各种测试,False即未通过测试。

    除了以上描述的CI流水线之外,在CI测试通过之后,另一个流水线可以接管余下的过程,以处理发布过程的CD部分。在这一阶段,流水线将尝试将应用程序容器交付到生产中。

    需要明白的是,这些操作是按需运行或者是由各种行为(如代码check-in、测试触发器、流程中上一步的结果等)自动触发的。因此我们需要一种机制来增加单个节点以运行那些流水线的步骤,并在不需要它们时将其淘汰。这种管理不可变基础架构的方法有助于我们节省资源并降低成本。

    当然,最关键的机制就是Kubernetes,它具有声明式的结构和可定制性,因此可以让你在任何场景下高效地调度job、节点以及pod。

    本文包括3个部分:第一部分我们将探讨目前在Kubernetes上运行最受欢迎的CI/CD平台。

    接着我们将会看两个用例:第一个例子中,我们将简单地在Kubernetes上安装Jenkins以及对其进行配置以让我们可以在Kubernetes上使用这个流行的开源工具来运行我们的CI流水线;第二个例子中,我们将把这个Jenkins部署提高到一个新的水平。我们将会提供一些在Kubernetes中扩展CI/CD流水线的tips和建议。

    最后,我们将会讨论在Kubernetes上大规模运行CI/CD的最合理的方法和实践。

    本文的目标是让你彻底了解Kubernetes处理这些工作负载的效率。

    适用于Kubernetes的CI/CD平台

    Kubernetes是一个运行CI/CD的理想平台,因为它拥有许多特性使得在上面运行CI/CD更为简单。那么,到底有多少CI/CD的平台可以在Kubernetes上运行呢?可以这么说,只要它们能够被打包为一个容器,Kubernetes都能够运行它们。以下是几个最为流行的CI/CD平台:

    • Jenkins:Jenkins是最为流行也最为稳定的CI/CD平台。在世界范围内有数以千计的企业都在使用它,因为它拥有强大的生态和可扩展性。如果你打算要在Kubernetes上使用它,非常建议你安装它的官方插件。JenkinsX是专门为云原生领域设计的Jenkins版本。它与Kubernetes更加兼容,并且提供了更好的集成功能,如GitOps、自动CI/CD和预览环境。
    • Spinnaker:Spinnaker是一个可扩展的多云部署的CD平台,得到了Netflix的支持。使用相关的Helm Chart即可安装它。

      https://github.com/helm/charts … naker

    • Drone:这是有多种功能的通用云原生CD平台。可以使用关联的Runner在Kubernetes中运行它。
    • GoCD:Thoughtworks的另一个CI/CD平台,提供了适用于云原生部署的各种工作流程和功能。它可以在Kubernetes中作为Helm Chart运行。

    此外,还有一些与Kubernetes紧密合作的云服务,并提供诸如CircleCI和Travis的CI/CD流水线。如果你不打算托管CI/CD平台,那么这些也十分有用。

    现在,我们来看看如何在Kubernetes集群上安装Jenkins。

    如何在Kubernetes上安装Jenkins

    首先,我们需要安装Helm,它是Kubernetes的软件包管理器:

    $ curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 > get_helm.sh
    $ chmod 700 get_helm.sh
    $ ./get_helm.sh -v v2.15.0

    同样,我们还需要安装Tiller,以让Helm正常运行:

    $ kubectl -n kube-system create serviceaccount tiller
    serviceaccount/tiller created

    ~/.kube
    $ kubectl create clusterrolebinding tiller --clusterrole cluster-admin --serviceaccount=kube-system:tiller
    clusterrolebinding.rbac.authorization.k8s.io/tiller created

    ~/.kube
    $ helm init --service-account tiller
    $HELM_HOME has been configured at /Users/itspare/.helm.

    完成这些步骤之后,我们需要运行检查命令,以查看deployment的配置值:

    $ helm inspect values stable/jenkins > values.yml

    仔细检查配置值并在需要的时候进行更改。然后安装Chart:

    $ helm install stable/jenkins --tls \
    --name jenkins \
    --namespace jenkins

    安装过程中会有一些关于下一步操作的说明:

    注意:

    1.  运行以下命令获取”admin“用户的密码:
    printf $(kubectl get secret --namespace default my-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo

    1. 在相同的shell中获取Jenkins URL以访问这些命令:

    export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/component=jenkins-master" -l "app.kubernetes.io/instance=my-jenkins" -o jsonpath="{.items[0].metadata.name}")
    echo http://127.0.0.1:8080
    kubectl --namespace default port-forward $POD_NAME 8080:8080

    遵循这些步骤,它们将在http://127.0.0.1:8080 启动代理服务器。

    到那里输入你的用户名和密码。你将会拥有自己的Jenkins 服务器:

    不过,请记住,还有许多配置选项尚未修改,你可以访问chart文档以了解更多信息:

    https://github.com/helm/charts … nkins

    在默认情况下,服务器会安装好最基本的插件,如Git和Kubernetes-Jenkins,我们可以根据自己的需要安装其他插件。

    总而言之,使用Helm安装Jenkins十分轻松。

    使用K8S扩展CI/CD Jenkins流水线

    既然我们已经大致了解CI/CD如何在Kubernetes上运行的,那么我们来看一个在Kubernetes中部署高度可扩展的Jenkins部署的示例用例。人们通常用它(进行了少量修改)来处理基础结构的CI/CD,开始吧!

    使用Jenkins固定发行版

    虽然官方Jenkins镜像很适合入门,但它需要的配置超出了我们的期望。许多用户会选择一个固定的发行版,如my-bloody-jenkins(https://github.com/odavid/my-bloody-jenkins ),它提供了一个较为完整的预安装插件以及配置选项。在可用的插件中,我们使用saml插件、SonarQubeRunner、Maven和Gradle。

    它能够使用以下命令通过Helm Chart安装:

    $ helm repo add odavid https://odavid.github.io/k8s-helm-charts
    $ helm install odavid/my-bloody-jenkins

    我们选择使用以下Dockerfile部署自定义镜像:

    FROM odavid/my-bloody-jenkins:2.190.2-161

    USER jenkins

    COPY plugins.txt /usr/share/jenkins/ref/
    RUN /usr/local/bin/install-plugins.sh 
    USER root

    其中plugins.txt文件是我们要预安装到镜像中的其他插件列表:

    build-monitor-plugin
    xcode-plugin
    rich-text-publisher-plugin
    jacoco
    scoverage
    dependency-check-jenkins-plugin
    greenballs
    shiningpanda
    pyenv-pipeline
    s3
    pipeline-aws
    appcenter
    multiple-scms
    Testng-plugin

    然后,只要dockerfile发生更改,我们就使用此通用Jenkinsfile来构建master:

    !/usr/bin/env groovy

    node('generic') {
    try {

    def dockerTag, jenkins_master

    stage('Checkout') {
    checkout([
    $class: 'GitSCM',
    branches: scm.branches,
    doGenerateSubmoduleConfigurations: scm.doGenerateSubmoduleConfigurations,
    extensions: [[$class: 'CloneOption', noTags: false, shallow: false, depth: 0, reference: '']],
    userRemoteConfigs: scm.userRemoteConfigs,
    ])

    def version = sh(returnStdout: true, script: "git describe --tags `git rev-list --tags --max-count=1`").trim()
    def tag = sh(returnStdout: true, script: "git rev-parse --short HEAD").trim()
    dockerTag = version + "-" + tag
    println("Tag: " + tag + " Version: " + version)
    }

    stage('Build Master') {
    jenkins_master = docker.build("jenkins-master", "--network=host .")
    }

    stage('Push images') {
    docker.withRegistry("https://$env.DOCKER_REGISTRY", 'ecr:eu-west-2:jenkins-aws-credentials') {
    jenkins_master.push("${dockerTag}")
    }
    }

    if(env.BRANCH_NAME == 'master') {

    stage('Push Latest images') {
    docker.withRegistry("https://$env.DOCKER_REGISTRY", 'ecr:eu-west-2:jenkins-aws-credentials') {
    jenkins_master.push("latest")
    }
    }

    stage('Deploy to K8s cluster') {
    withKubeConfig([credentialsId: 'dev-tools-eks-jenkins-secret',
    serverUrl: env.TOOLS_EKS_URL]) {
    sh "kubectl set image statefulset jenkins jenkins=$env.DOCKER_REGISTRY/jenkins-master:${dockerTag}"
    }
    }
    }
    currentBuild.result = 'SUCCESS'
    } catch(e) {
    currentBuild.result = 'FAILURE'
    throw e
    }
    }

    我们所使用的专用集群由AWS中的一些大中型实例组成,用于Jenkins jobs。接下来,我们进入下一个部分。

    使用专用的Jenkins Slaves和标签(label)

    为了扩展我们的一些Jenkins slaves,我们使用Pod模板并将标签分配给特定的agent。因此在我们的Jenkinsfiles中,我们可以为jobs引用它们。例如,我们有一些需要构建安卓应用程序的agent。因此,我们引用以下标签:

    pipeline {
    agent { label "android" }

    并且将使用特定于安卓的pod模板。我们使用这一Dockerfile,例如:

    FROM dkr.ecr.eu-west-2.amazonaws.com/jenkins-jnlp-slave:latest

    RUN apt-get update && apt-get install -y -f --no-install-recommends xmlstarlet

    ARG GULP_VERSION=4.0.0
    ARG CORDOVA_VERSION=8.0.0

    SDK version and build-tools version should be different

    ENV SDK_VERSION 25.2.3
    ENV BUILD_TOOLS_VERSION 26.0.2
    ENV SDK_CHECKSUM 1b35bcb94e9a686dff6460c8bca903aa0281c6696001067f34ec00093145b560
    ENV ANDROID_HOME /opt/android-sdk
    ENV SDK_UPDATE tools,platform-tools,build-tools-25.0.2,android-25,android-24,android-23,android-22,android-21,sys-img-armeabi-v7a-android-26,sys-img-x86-android-23
    ENV LD_LIBRARY_PATH ${ANDROID_HOME}/tools/lib64/qt:${ANDROID_HOME}/tools/lib/libQt5:$LD_LIBRARY_PATH/
    ENV PATH ${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools

    RUN curl -SLO "https://dl.google.com/android/repository/tools_r${SDK_VERSION}-linux.zip" \
    && echo "${SDK_CHECKSUM} tools_r${SDK_VERSION}-linux.zip" | sha256sum -c - \
    && mkdir -p "${ANDROID_HOME}" \
    && unzip -qq "tools_r${SDK_VERSION}-linux.zip" -d "${ANDROID_HOME}" \
    && rm -Rf "tools_r${SDK_VERSION}-linux.zip" \
    && echo y | ${ANDROID_HOME}/tools/android update sdk --filter ${SDK_UPDATE} --all --no-ui --force \
    && mkdir -p ${ANDROID_HOME}/tools/keymaps \
    && touch ${ANDROID_HOME}/tools/keymaps/en-us \
    && yes | ${ANDROID_HOME}/tools/bin/sdkmanager --update

    RUN chmod -R 777 ${ANDROID_HOME} && chown -R jenkins:jenkins ${ANDROID_HOME}

    我们还使用了Jenkinsfile,该文件与上一个文件类似,用于构建master。每当我们对Dockerfile进行更改时,agent都会重建镜像。这为我们的CI/CD基础架构提供了极大的灵活性。

    使用自动伸缩

    尽管我们为deployment分配了特定数量的节点,但我们还可以通过启用cluster autoscaling,来完成更多的事情。这意味着在工作负载增加和峰值的情况下,我们可以增加额外的节点来处理job。目前,如果我们有固定数量的节点,那么我们只能处理固定数量的job。基于以下事实,我们可以进行粗略地估计:每个slave通常分配500ms CPU和256MB内存,并且设置一个很高的并发。这根本不现实。

    举个例子,当你的版本被大幅削减并且需要部署大量微服务时,可能会发生上述情况。然后,大量的job堆积在流水线,造成严重的延误。

    在这种情况下,我们可以增加该阶段的节点数。例如,我们可以添加额外的VM实例,然后在过程结束时将其删除。

    我们可以在命令行中使用自动伸缩选项来配置“Vertical”或“集群”自动伸缩选项。但是,此方法需要仔细计划和配置,因为有时会发生以下情况:

    1. 越来越多的job达到平稳阶段
    2. Autoscaler增加新的节点,但是需要10分钟来进行部署和分配
    3. 旧的job已经完成任务,新的job将填补空白,进而减少了对新节点的需求
    4. 新节点可用,但需要X分钟保持稳定且未利用,X由–scale-down-unneeded-time标志定义
    5. 同样的事情每天发生很多次

    在这种情况下,最好是根据我们的特定需求进行配置,或者只是增加当天的节点数,并在流程结束后将其还原。所有这些都与寻找最佳方法来利用所有资源并使成本最小化有关。

    在任何情况下,我们都应该有一个可伸缩且易于使用的Jenkins集群。对于每个job,都会创建一个pod来运行特定的流水线,并在完成后将其销毁。

    大规模使用K8s进行CI / CD的最佳实践

    现在我们已经了解了Kubernetes有哪些CI/CD平台以及如何在你的集群上安装一个平台。接下来,我们将讨论一些大规模运行它们的方法。

    首先,选择Kubernetes发行版是我们需要考虑的最关键因素之一。找到最合适的解决方案才能够进行下一步。

    其次,选择合适的Docker镜像仓库和应用程序包管理器同样重要。我们需要寻找可以按需快速检索的安全可靠的镜像管理。至于软件包管理器,Helm是一个不错的选择,因为它可以发现、共享和使用为Kubernetes构建的软件。

    第三,使用现代集成流程,如GitOps和ChatOps,在易用性和可预测性方面提供了显著优势。将Git用作单一数据源,使我们可以运行“通过拉取请求进行操作”,从而简化了对基础架构和应用程序的部署控制。使用诸如企业微信或钉钉之类的团队协作工作来触发CI/CD流水线的自动化任务,有助于我们消除重复劳动并简化集成。

    总体而言,如果我们想更深入地了解,你可以自定义或开发自己的K8S Operator,与K8S API配合更紧密。使用自定义operator的好处很多,因为它们可以建立更好的自动化体验。

    最后,我们可以说Kubernetes和CI/CD平台是天合之作。如果你刚刚入门Kubernetes生态系统,那么你可以尝试集成一个CI/CD流水线。这是了解Kubernetes内部运作方式的好方法,关键是要留出机动空间,方便将来容易更改。

    2020年2月18日 | by 灵雀云

    请把 .gitattributes 加到你的 Git 仓库中

    什么是 .gitattributes ?
    当执行 git 动作时,.gitattributes 文件允许你指定由 git 使用的文件和路径的属性,例如:git commit 等。
    换句话说,每当有文件保存或者创建时,git 会根据指定的属性来自动地保存。
    其中的一个属性是 eol(end of line),用于配置文件的结尾。本文将会深入了解如何配置文件的结尾行,这样的话,即使在不同的机器、操作系统 上都可以使得每个开发者都可以使用相同的值。
    为什么是 .gitattributes(开发者之间的争议…

    2020年2月18日 | by Ana Ware

    How is data growth affecting real-world enterprises? 4 key findings

    Data volumes are expanding at an unprecedented rate. It’s very easy to get caught up in how many zettabytes of data we’ll all be producing by 2025, 2030, and beyond,  and how data and cloud computing affect us all on a global scale. But what do data growth and other issues mean for how you Read more…

    The post How is data growth affecting real-world enterprises? 4 key findings appeared first on Datanami.

    2020年2月17日 | by Articles RSS feed - Mod DB

    VR version released on Steam

    VR version of First Person Strategy No King No Kingdom is released on Steam with Oculus Rift and HTC Vive support.

    2020年2月17日 | by Articles RSS feed - Mod DB

    V0.7

    News about the last update of the game. New faction, bug correction, etc…

    2020年2月17日 | by Articles RSS feed - Mod DB

    Teaser (v0.3-alpha) – Ship Thumbnails

    Adding ship thumbnails for all of the current ships (and adding a few more ships as well). This will make the shipyard screen far less laggy!

    *Sigh… this will take ages.

    2020年2月17日 | by Articles RSS feed - Mod DB

    RL 1.9 Release

    Residual Life in Half-Life 1 mod, it was developed from 2008 to 2020.

    关注我们的微信公众号获取更多健身信息
    蜀ICP备15013372号